The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/axgbe/xgbe-mdio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * AMD 10Gb Ethernet driver
    3  *
    4  * Copyright (c) 2014-2016,2020 Advanced Micro Devices, Inc.
    5  *
    6  * This file is available to you under your choice of the following two
    7  * licenses:
    8  *
    9  * License 1: GPLv2
   10  *
   11  * This file is free software; you may copy, redistribute and/or modify
   12  * it under the terms of the GNU General Public License as published by
   13  * the Free Software Foundation, either version 2 of the License, or (at
   14  * your option) any later version.
   15  *
   16  * This file is distributed in the hope that it will be useful, but
   17  * WITHOUT ANY WARRANTY; without even the implied warranty of
   18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   19  * General Public License for more details.
   20  *
   21  * You should have received a copy of the GNU General Public License
   22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   23  *
   24  * This file incorporates work covered by the following copyright and
   25  * permission notice:
   26  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
   27  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
   28  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
   29  *     and you.
   30  *
   31  *     The Software IS NOT an item of Licensed Software or Licensed Product
   32  *     under any End User Software License Agreement or Agreement for Licensed
   33  *     Product with Synopsys or any supplement thereto.  Permission is hereby
   34  *     granted, free of charge, to any person obtaining a copy of this software
   35  *     annotated with this license and the Software, to deal in the Software
   36  *     without restriction, including without limitation the rights to use,
   37  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   38  *     of the Software, and to permit persons to whom the Software is furnished
   39  *     to do so, subject to the following conditions:
   40  *
   41  *     The above copyright notice and this permission notice shall be included
   42  *     in all copies or substantial portions of the Software.
   43  *
   44  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
   45  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   46  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   47  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
   48  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   49  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   50  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   51  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   52  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   53  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   54  *     THE POSSIBILITY OF SUCH DAMAGE.
   55  *
   56  *
   57  * License 2: Modified BSD
   58  *
   59  * Redistribution and use in source and binary forms, with or without
   60  * modification, are permitted provided that the following conditions are met:
   61  *     * Redistributions of source code must retain the above copyright
   62  *       notice, this list of conditions and the following disclaimer.
   63  *     * Redistributions in binary form must reproduce the above copyright
   64  *       notice, this list of conditions and the following disclaimer in the
   65  *       documentation and/or other materials provided with the distribution.
   66  *     * Neither the name of Advanced Micro Devices, Inc. nor the
   67  *       names of its contributors may be used to endorse or promote products
   68  *       derived from this software without specific prior written permission.
   69  *
   70  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   71  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   73  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
   74  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   75  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   76  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   77  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   78  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   79  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   80  *
   81  * This file incorporates work covered by the following copyright and
   82  * permission notice:
   83  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
   84  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
   85  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
   86  *     and you.
   87  *
   88  *     The Software IS NOT an item of Licensed Software or Licensed Product
   89  *     under any End User Software License Agreement or Agreement for Licensed
   90  *     Product with Synopsys or any supplement thereto.  Permission is hereby
   91  *     granted, free of charge, to any person obtaining a copy of this software
   92  *     annotated with this license and the Software, to deal in the Software
   93  *     without restriction, including without limitation the rights to use,
   94  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   95  *     of the Software, and to permit persons to whom the Software is furnished
   96  *     to do so, subject to the following conditions:
   97  *
   98  *     The above copyright notice and this permission notice shall be included
   99  *     in all copies or substantial portions of the Software.
  100  *
  101  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  102  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  103  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  104  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
  105  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  106  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  107  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  108  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  109  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  110  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  111  *     THE POSSIBILITY OF SUCH DAMAGE.
  112  */
  113 
  114 #include <sys/cdefs.h>
  115 __FBSDID("$FreeBSD$");
  116 
  117 #include "xgbe.h"
  118 #include "xgbe-common.h"
  119 
  120 static void xgbe_an_state_machine(struct xgbe_prv_data *pdata);
  121 
  122 static void
  123 xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
  124 {
  125         int reg;
  126 
  127         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
  128         reg &= ~XGBE_AN_CL37_INT_MASK;
  129         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
  130 }
  131 
  132 static void
  133 xgbe_an37_disable_interrupts(struct xgbe_prv_data *pdata)
  134 {
  135         int reg;
  136 
  137         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
  138         reg &= ~XGBE_AN_CL37_INT_MASK;
  139         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
  140 
  141         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
  142         reg &= ~XGBE_PCS_CL37_BP;
  143         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
  144 }
  145 
  146 static void
  147 xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata)
  148 {
  149         int reg;
  150 
  151         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
  152         reg |= XGBE_PCS_CL37_BP;
  153         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
  154 
  155         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
  156         reg |= XGBE_AN_CL37_INT_MASK;
  157         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
  158 }
  159 
  160 static void
  161 xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata)
  162 {
  163         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
  164 }
  165 
  166 static void
  167 xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata)
  168 {
  169         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
  170 }
  171 
  172 static void
  173 xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata)
  174 {
  175         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK);
  176 }
  177 
  178 static void
  179 xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata)
  180 {
  181         switch (pdata->an_mode) {
  182         case XGBE_AN_MODE_CL73:
  183         case XGBE_AN_MODE_CL73_REDRV:
  184                 xgbe_an73_enable_interrupts(pdata);
  185                 break;
  186         case XGBE_AN_MODE_CL37:
  187         case XGBE_AN_MODE_CL37_SGMII:
  188                 xgbe_an37_enable_interrupts(pdata);
  189                 break;
  190         default:
  191                 break;
  192         }
  193 }
  194 
  195 static void
  196 xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata)
  197 {
  198         xgbe_an73_clear_interrupts(pdata);
  199         xgbe_an37_clear_interrupts(pdata);
  200 }
  201 
  202 static void
  203 xgbe_kr_mode(struct xgbe_prv_data *pdata)
  204 {
  205         /* Set MAC to 10G speed */
  206         pdata->hw_if.set_speed(pdata, SPEED_10000);
  207 
  208         /* Call PHY implementation support to complete rate change */
  209         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
  210 }
  211 
  212 static void
  213 xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
  214 {
  215         /* Set MAC to 2.5G speed */
  216         pdata->hw_if.set_speed(pdata, SPEED_2500);
  217 
  218         /* Call PHY implementation support to complete rate change */
  219         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
  220 }
  221 
  222 static void
  223 xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
  224 {
  225         /* Set MAC to 1G speed */
  226         pdata->hw_if.set_speed(pdata, SPEED_1000);
  227 
  228         /* Call PHY implementation support to complete rate change */
  229         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
  230 }
  231 
  232 static void
  233 xgbe_sfi_mode(struct xgbe_prv_data *pdata)
  234 {
  235         /* If a KR re-driver is present, change to KR mode instead */
  236         if (pdata->kr_redrv)
  237                 return (xgbe_kr_mode(pdata));
  238 
  239         /* Set MAC to 10G speed */
  240         pdata->hw_if.set_speed(pdata, SPEED_10000);
  241 
  242         /* Call PHY implementation support to complete rate change */
  243         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SFI);
  244 }
  245 
  246 static void
  247 xgbe_x_mode(struct xgbe_prv_data *pdata)
  248 {
  249         /* Set MAC to 1G speed */
  250         pdata->hw_if.set_speed(pdata, SPEED_1000);
  251 
  252         /* Call PHY implementation support to complete rate change */
  253         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_X);
  254 }
  255 
  256 static void
  257 xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
  258 {
  259         /* Set MAC to 1G speed */
  260         pdata->hw_if.set_speed(pdata, SPEED_1000);
  261 
  262         /* Call PHY implementation support to complete rate change */
  263         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_1000);
  264 }
  265 
  266 static void
  267 xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
  268 {
  269         /* Set MAC to 1G speed */
  270         pdata->hw_if.set_speed(pdata, SPEED_1000);
  271 
  272         /* Call PHY implementation support to complete rate change */
  273         pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_100);
  274 }
  275 
  276 static enum xgbe_mode
  277 xgbe_cur_mode(struct xgbe_prv_data *pdata)
  278 {
  279         return (pdata->phy_if.phy_impl.cur_mode(pdata));
  280 }
  281 
  282 static bool
  283 xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
  284 {
  285         return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
  286 }
  287 
  288 static void
  289 xgbe_change_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
  290 {
  291         switch (mode) {
  292         case XGBE_MODE_KX_1000:
  293                 xgbe_kx_1000_mode(pdata);
  294                 break;
  295         case XGBE_MODE_KX_2500:
  296                 xgbe_kx_2500_mode(pdata);
  297                 break;
  298         case XGBE_MODE_KR:
  299                 xgbe_kr_mode(pdata);
  300                 break;
  301         case XGBE_MODE_SGMII_100:
  302                 xgbe_sgmii_100_mode(pdata);
  303                 break;
  304         case XGBE_MODE_SGMII_1000:
  305                 xgbe_sgmii_1000_mode(pdata);
  306                 break;
  307         case XGBE_MODE_X:
  308                 xgbe_x_mode(pdata);
  309                 break;
  310         case XGBE_MODE_SFI:
  311                 xgbe_sfi_mode(pdata);
  312                 break;
  313         case XGBE_MODE_UNKNOWN:
  314                 break;
  315         default:
  316                 axgbe_error("invalid operation mode requested (%u)\n", mode);
  317         }
  318 }
  319 
  320 static void
  321 xgbe_switch_mode(struct xgbe_prv_data *pdata)
  322 {
  323         xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
  324 }
  325 
  326 static bool
  327 xgbe_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
  328 {
  329         if (mode == xgbe_cur_mode(pdata))
  330                 return (false);
  331 
  332         xgbe_change_mode(pdata, mode);
  333 
  334         return (true);
  335 }
  336 
  337 static bool
  338 xgbe_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
  339 {
  340         return (pdata->phy_if.phy_impl.use_mode(pdata, mode));
  341 }
  342 
  343 static void
  344 xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, bool restart)
  345 {
  346         unsigned int reg;
  347 
  348         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1);
  349         reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE;
  350 
  351         if (enable)
  352                 reg |= MDIO_VEND2_CTRL1_AN_ENABLE;
  353 
  354         if (restart)
  355                 reg |= MDIO_VEND2_CTRL1_AN_RESTART;
  356 
  357         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
  358 }
  359 
  360 static void
  361 xgbe_an37_restart(struct xgbe_prv_data *pdata)
  362 {
  363         xgbe_an37_enable_interrupts(pdata);
  364         xgbe_an37_set(pdata, true, true);
  365 }
  366 
  367 static void
  368 xgbe_an37_disable(struct xgbe_prv_data *pdata)
  369 {
  370         xgbe_an37_set(pdata, false, false);
  371         xgbe_an37_disable_interrupts(pdata);
  372 }
  373 
  374 static void
  375 xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable, bool restart)
  376 {
  377         unsigned int reg;
  378 
  379         /* Disable KR training for now */
  380         reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
  381         reg &= ~XGBE_KR_TRAINING_ENABLE;
  382         XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
  383 
  384         /* Update AN settings */
  385         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
  386         reg &= ~MDIO_AN_CTRL1_ENABLE;
  387 
  388         if (enable)
  389                 reg |= MDIO_AN_CTRL1_ENABLE;
  390 
  391         if (restart)
  392                 reg |= MDIO_AN_CTRL1_RESTART;
  393 
  394         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
  395 }
  396 
  397 static void
  398 xgbe_an73_restart(struct xgbe_prv_data *pdata)
  399 {
  400         xgbe_an73_enable_interrupts(pdata);
  401         xgbe_an73_set(pdata, true, true);
  402 }
  403 
  404 static void
  405 xgbe_an73_disable(struct xgbe_prv_data *pdata)
  406 {
  407         xgbe_an73_set(pdata, false, false);
  408         xgbe_an73_disable_interrupts(pdata);
  409 
  410         pdata->an_start = 0;
  411 }
  412 
  413 static void
  414 xgbe_an_restart(struct xgbe_prv_data *pdata)
  415 {
  416         if (pdata->phy_if.phy_impl.an_pre)
  417                 pdata->phy_if.phy_impl.an_pre(pdata);
  418 
  419         switch (pdata->an_mode) {
  420         case XGBE_AN_MODE_CL73:
  421         case XGBE_AN_MODE_CL73_REDRV:
  422                 xgbe_an73_restart(pdata);
  423                 break;
  424         case XGBE_AN_MODE_CL37:
  425         case XGBE_AN_MODE_CL37_SGMII:
  426                 xgbe_an37_restart(pdata);
  427                 break;
  428         default:
  429                 break;
  430         }
  431 }
  432 
  433 static void
  434 xgbe_an_disable(struct xgbe_prv_data *pdata)
  435 {
  436         if (pdata->phy_if.phy_impl.an_post)
  437                 pdata->phy_if.phy_impl.an_post(pdata);
  438 
  439         switch (pdata->an_mode) {
  440         case XGBE_AN_MODE_CL73:
  441         case XGBE_AN_MODE_CL73_REDRV:
  442                 xgbe_an73_disable(pdata);
  443                 break;
  444         case XGBE_AN_MODE_CL37:
  445         case XGBE_AN_MODE_CL37_SGMII:
  446                 xgbe_an37_disable(pdata);
  447                 break;
  448         default:
  449                 break;
  450         }
  451 }
  452 
  453 static void
  454 xgbe_an_disable_all(struct xgbe_prv_data *pdata)
  455 {
  456         xgbe_an73_disable(pdata);
  457         xgbe_an37_disable(pdata);
  458 }
  459 
  460 static enum xgbe_an
  461 xgbe_an73_tx_training(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
  462 {
  463         unsigned int ad_reg, lp_reg, reg;
  464 
  465         *state = XGBE_RX_COMPLETE;
  466 
  467         /* If we're not in KR mode then we're done */
  468         if (!xgbe_in_kr_mode(pdata))
  469                 return (XGBE_AN_PAGE_RECEIVED);
  470 
  471         /* Enable/Disable FEC */
  472         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
  473         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
  474 
  475         reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL);
  476         reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE);
  477         if ((ad_reg & 0xc000) && (lp_reg & 0xc000))
  478                 reg |= pdata->fec_ability;
  479 
  480         XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
  481 
  482         /* Start KR training */
  483         if (pdata->phy_if.phy_impl.kr_training_pre)
  484                 pdata->phy_if.phy_impl.kr_training_pre(pdata);
  485 
  486         /* Start KR training */
  487         reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
  488         reg |= XGBE_KR_TRAINING_ENABLE;
  489         reg |= XGBE_KR_TRAINING_START;
  490         XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
  491 
  492         if (pdata->phy_if.phy_impl.kr_training_post)
  493                 pdata->phy_if.phy_impl.kr_training_post(pdata);
  494 
  495         return (XGBE_AN_PAGE_RECEIVED);
  496 }
  497 
  498 static enum xgbe_an
  499 xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
  500 {
  501         uint16_t msg;
  502 
  503         *state = XGBE_RX_XNP;
  504 
  505         msg = XGBE_XNP_MCF_NULL_MESSAGE;
  506         msg |= XGBE_XNP_MP_FORMATTED;
  507 
  508         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0);
  509         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0);
  510         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP, msg);
  511 
  512         return (XGBE_AN_PAGE_RECEIVED);
  513 }
  514 
  515 static enum xgbe_an
  516 xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
  517 {
  518         unsigned int link_support;
  519         unsigned int reg, ad_reg, lp_reg;
  520 
  521         /* Read Base Ability register 2 first */
  522         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
  523 
  524         /* Check for a supported mode, otherwise restart in a different one */
  525         link_support = xgbe_in_kr_mode(pdata) ? 0x80 : 0x20;
  526         if (!(reg & link_support))
  527                 return (XGBE_AN_INCOMPAT_LINK);
  528 
  529         /* Check Extended Next Page support */
  530         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
  531         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
  532 
  533         return (((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
  534                 (lp_reg & XGBE_XNP_NP_EXCHANGE))
  535                ? xgbe_an73_tx_xnp(pdata, state)
  536                : xgbe_an73_tx_training(pdata, state));
  537 }
  538 
  539 static enum xgbe_an
  540 xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
  541 {
  542         unsigned int ad_reg, lp_reg;
  543 
  544         /* Check Extended Next Page support */
  545         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_XNP);
  546         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPX);
  547 
  548         return (((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
  549                 (lp_reg & XGBE_XNP_NP_EXCHANGE))
  550                ? xgbe_an73_tx_xnp(pdata, state)
  551                : xgbe_an73_tx_training(pdata, state));
  552 }
  553 
  554 static enum xgbe_an
  555 xgbe_an73_page_received(struct xgbe_prv_data *pdata)
  556 {
  557         enum xgbe_rx *state;
  558         unsigned long an_timeout;
  559         enum xgbe_an ret;
  560 
  561         if (!pdata->an_start) {
  562                 pdata->an_start = ticks;
  563         } else {
  564                 an_timeout = pdata->an_start +
  565                     ((uint64_t)XGBE_AN_MS_TIMEOUT * (uint64_t)hz) / 1000ull;
  566                 if ((int)(ticks - an_timeout) > 0) {
  567                         /* Auto-negotiation timed out, reset state */
  568                         pdata->kr_state = XGBE_RX_BPA;
  569                         pdata->kx_state = XGBE_RX_BPA;
  570 
  571                         pdata->an_start = ticks;
  572 
  573                         axgbe_printf(2, "CL73 AN timed out, resetting state\n");
  574                 }
  575         }
  576 
  577         state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state : &pdata->kx_state;
  578 
  579         switch (*state) {
  580         case XGBE_RX_BPA:
  581                 ret = xgbe_an73_rx_bpa(pdata, state);
  582                 break;
  583 
  584         case XGBE_RX_XNP:
  585                 ret = xgbe_an73_rx_xnp(pdata, state);
  586                 break;
  587 
  588         default:
  589                 ret = XGBE_AN_ERROR;
  590         }
  591 
  592         return (ret);
  593 }
  594 
  595 static enum xgbe_an
  596 xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
  597 {
  598         /* Be sure we aren't looping trying to negotiate */
  599         if (xgbe_in_kr_mode(pdata)) {
  600                 pdata->kr_state = XGBE_RX_ERROR;
  601 
  602                 if (!(XGBE_ADV(&pdata->phy, 1000baseKX_Full)) &&
  603                     !(XGBE_ADV(&pdata->phy, 2500baseX_Full)))
  604                         return (XGBE_AN_NO_LINK);
  605 
  606                 if (pdata->kx_state != XGBE_RX_BPA)
  607                         return (XGBE_AN_NO_LINK);
  608         } else {
  609                 pdata->kx_state = XGBE_RX_ERROR;
  610 
  611                 if (!(XGBE_ADV(&pdata->phy, 10000baseKR_Full)))
  612                         return (XGBE_AN_NO_LINK);
  613 
  614                 if (pdata->kr_state != XGBE_RX_BPA)
  615                         return (XGBE_AN_NO_LINK);
  616         }
  617 
  618         xgbe_an_disable(pdata);
  619 
  620         xgbe_switch_mode(pdata);
  621 
  622         xgbe_an_restart(pdata);
  623 
  624         return (XGBE_AN_INCOMPAT_LINK);
  625 }
  626 
  627 static void
  628 xgbe_an37_isr(struct xgbe_prv_data *pdata)
  629 {
  630         unsigned int reg;
  631 
  632         /* Disable AN interrupts */
  633         xgbe_an37_disable_interrupts(pdata);
  634 
  635         /* Save the interrupt(s) that fired */
  636         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
  637         pdata->an_int = reg & XGBE_AN_CL37_INT_MASK;
  638         pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK;
  639 
  640         if (pdata->an_int) {
  641                 /* Clear the interrupt(s) that fired and process them */
  642                 reg &= ~XGBE_AN_CL37_INT_MASK;
  643                 XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
  644 
  645                 xgbe_an_state_machine(pdata);
  646         } else {
  647                 /* Enable AN interrupts */
  648                 xgbe_an37_enable_interrupts(pdata);
  649 
  650                 /* Reissue interrupt if status is not clear */
  651                 if (pdata->vdata->irq_reissue_support)
  652                         XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
  653         }
  654 }
  655 
  656 static void
  657 xgbe_an73_isr(struct xgbe_prv_data *pdata)
  658 {
  659         /* Disable AN interrupts */
  660         xgbe_an73_disable_interrupts(pdata);
  661 
  662         /* Save the interrupt(s) that fired */
  663         pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
  664 
  665         if (pdata->an_int) {
  666                 /* Clear the interrupt(s) that fired and process them */
  667                 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
  668 
  669                 xgbe_an_state_machine(pdata);
  670         } else {
  671                 /* Enable AN interrupts */
  672                 xgbe_an73_enable_interrupts(pdata);
  673 
  674                 /* Reissue interrupt if status is not clear */
  675                 if (pdata->vdata->irq_reissue_support)
  676                         XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
  677         }
  678 }
  679 
  680 static void
  681 xgbe_an_isr_task(unsigned long data)
  682 {
  683         struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
  684 
  685         axgbe_printf(2, "AN interrupt received\n");
  686 
  687         switch (pdata->an_mode) {
  688         case XGBE_AN_MODE_CL73:
  689         case XGBE_AN_MODE_CL73_REDRV:
  690                 xgbe_an73_isr(pdata);
  691                 break;
  692         case XGBE_AN_MODE_CL37:
  693         case XGBE_AN_MODE_CL37_SGMII:
  694                 xgbe_an37_isr(pdata);
  695                 break;
  696         default:
  697                 break;
  698         }
  699 }
  700 
  701 static void
  702 xgbe_an_combined_isr(struct xgbe_prv_data *pdata)
  703 {
  704         xgbe_an_isr_task((unsigned long)pdata);
  705 }
  706 
  707 static const char *
  708 xgbe_state_as_string(enum xgbe_an state)
  709 {
  710         switch (state) {
  711         case XGBE_AN_READY:
  712                 return ("Ready");
  713         case XGBE_AN_PAGE_RECEIVED:
  714                 return ("Page-Received");
  715         case XGBE_AN_INCOMPAT_LINK:
  716                 return ("Incompatible-Link");
  717         case XGBE_AN_COMPLETE:
  718                 return ("Complete");
  719         case XGBE_AN_NO_LINK:
  720                 return ("No-Link");
  721         case XGBE_AN_ERROR:
  722                 return ("Error");
  723         default:
  724                 return ("Undefined");
  725         }
  726 }
  727 
  728 static void
  729 xgbe_an37_state_machine(struct xgbe_prv_data *pdata)
  730 {
  731         enum xgbe_an cur_state = pdata->an_state;
  732 
  733         if (!pdata->an_int)
  734                 return;
  735 
  736         if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) {
  737                 pdata->an_state = XGBE_AN_COMPLETE;
  738                 pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT;
  739 
  740                 /* If SGMII is enabled, check the link status */
  741                 if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) &&
  742                     !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS))
  743                         pdata->an_state = XGBE_AN_NO_LINK;
  744         }
  745 
  746         axgbe_printf(2, "%s: CL37 AN %s\n", __func__,
  747             xgbe_state_as_string(pdata->an_state));
  748 
  749         cur_state = pdata->an_state;
  750 
  751         switch (pdata->an_state) {
  752         case XGBE_AN_READY:
  753                 break;
  754 
  755         case XGBE_AN_COMPLETE:
  756                 axgbe_printf(2, "Auto negotiation successful\n");
  757                 break;
  758 
  759         case XGBE_AN_NO_LINK:
  760                 break;
  761 
  762         default:
  763                 pdata->an_state = XGBE_AN_ERROR;
  764         }
  765 
  766         if (pdata->an_state == XGBE_AN_ERROR) {
  767                 axgbe_printf(2, "error during auto-negotiation, state=%u\n",
  768                     cur_state);
  769 
  770                 pdata->an_int = 0;
  771                 xgbe_an37_clear_interrupts(pdata);
  772         }
  773 
  774         if (pdata->an_state >= XGBE_AN_COMPLETE) {
  775                 pdata->an_result = pdata->an_state;
  776                 pdata->an_state = XGBE_AN_READY;
  777 
  778                 if (pdata->phy_if.phy_impl.an_post)
  779                         pdata->phy_if.phy_impl.an_post(pdata);
  780 
  781                 axgbe_printf(2, "CL37 AN result: %s\n",
  782                     xgbe_state_as_string(pdata->an_result));
  783         }
  784 
  785         axgbe_printf(2, "%s: an_state %d an_int %d an_mode %d an_status %d\n",
  786              __func__, pdata->an_state, pdata->an_int, pdata->an_mode,
  787              pdata->an_status);
  788 
  789         xgbe_an37_enable_interrupts(pdata);
  790 }
  791 
  792 static void
  793 xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
  794 {
  795         enum xgbe_an cur_state = pdata->an_state;
  796 
  797         if (!pdata->an_int)
  798                 goto out;
  799 
  800 next_int:
  801         if (pdata->an_int & XGBE_AN_CL73_PG_RCV) {
  802                 pdata->an_state = XGBE_AN_PAGE_RECEIVED;
  803                 pdata->an_int &= ~XGBE_AN_CL73_PG_RCV;
  804         } else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) {
  805                 pdata->an_state = XGBE_AN_INCOMPAT_LINK;
  806                 pdata->an_int &= ~XGBE_AN_CL73_INC_LINK;
  807         } else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) {
  808                 pdata->an_state = XGBE_AN_COMPLETE;
  809                 pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT;
  810         } else {
  811                 pdata->an_state = XGBE_AN_ERROR;
  812         }
  813 
  814 again:
  815         axgbe_printf(2, "CL73 AN %s\n",
  816             xgbe_state_as_string(pdata->an_state));
  817 
  818         cur_state = pdata->an_state;
  819 
  820         switch (pdata->an_state) {
  821         case XGBE_AN_READY:
  822                 pdata->an_supported = 0;
  823                 break;
  824 
  825         case XGBE_AN_PAGE_RECEIVED:
  826                 pdata->an_state = xgbe_an73_page_received(pdata);
  827                 pdata->an_supported++;
  828                 break;
  829 
  830         case XGBE_AN_INCOMPAT_LINK:
  831                 pdata->an_supported = 0;
  832                 pdata->parallel_detect = 0;
  833                 pdata->an_state = xgbe_an73_incompat_link(pdata);
  834                 break;
  835 
  836         case XGBE_AN_COMPLETE:
  837                 pdata->parallel_detect = pdata->an_supported ? 0 : 1;
  838                 axgbe_printf(2, "%s successful\n",
  839                     pdata->an_supported ? "Auto negotiation"
  840                     : "Parallel detection");
  841                 break;
  842 
  843         case XGBE_AN_NO_LINK:
  844                 break;
  845 
  846         default:
  847                 pdata->an_state = XGBE_AN_ERROR;
  848         }
  849 
  850         if (pdata->an_state == XGBE_AN_NO_LINK) {
  851                 pdata->an_int = 0;
  852                 xgbe_an73_clear_interrupts(pdata);
  853         } else if (pdata->an_state == XGBE_AN_ERROR) {
  854                 axgbe_printf(2,
  855                     "error during auto-negotiation, state=%u\n",
  856                     cur_state);
  857 
  858                 pdata->an_int = 0;
  859                 xgbe_an73_clear_interrupts(pdata);
  860         }
  861 
  862         if (pdata->an_state >= XGBE_AN_COMPLETE) {
  863                 pdata->an_result = pdata->an_state;
  864                 pdata->an_state = XGBE_AN_READY;
  865                 pdata->kr_state = XGBE_RX_BPA;
  866                 pdata->kx_state = XGBE_RX_BPA;
  867                 pdata->an_start = 0;
  868 
  869                 if (pdata->phy_if.phy_impl.an_post)
  870                         pdata->phy_if.phy_impl.an_post(pdata);
  871 
  872                 axgbe_printf(2,  "CL73 AN result: %s\n",
  873                     xgbe_state_as_string(pdata->an_result));
  874         }
  875 
  876         if (cur_state != pdata->an_state)
  877                 goto again;
  878 
  879         if (pdata->an_int)
  880                 goto next_int;
  881 
  882 out:
  883         /* Enable AN interrupts on the way out */
  884         xgbe_an73_enable_interrupts(pdata);
  885 }
  886 
  887 static void
  888 xgbe_an_state_machine(struct xgbe_prv_data *pdata)
  889 {
  890         sx_xlock(&pdata->an_mutex);
  891 
  892         switch (pdata->an_mode) {
  893         case XGBE_AN_MODE_CL73:
  894         case XGBE_AN_MODE_CL73_REDRV:
  895                 xgbe_an73_state_machine(pdata);
  896                 break;
  897         case XGBE_AN_MODE_CL37:
  898         case XGBE_AN_MODE_CL37_SGMII:
  899                 xgbe_an37_state_machine(pdata);
  900                 break;
  901         default:
  902                 break;
  903         }
  904 
  905         /* Reissue interrupt if status is not clear */
  906         if (pdata->vdata->irq_reissue_support)
  907                 XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
  908 
  909         sx_xunlock(&pdata->an_mutex);
  910 }
  911 
  912 static void
  913 xgbe_an37_init(struct xgbe_prv_data *pdata)
  914 {
  915         struct xgbe_phy local_phy;
  916         unsigned int reg;
  917 
  918         pdata->phy_if.phy_impl.an_advertising(pdata, &local_phy);
  919 
  920         axgbe_printf(2, "%s: advertising 0x%x\n", __func__, local_phy.advertising);
  921 
  922         /* Set up Advertisement register */
  923         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
  924         if (XGBE_ADV(&local_phy, Pause))
  925                 reg |= 0x100;
  926         else
  927                 reg &= ~0x100;
  928 
  929         if (XGBE_ADV(&local_phy, Asym_Pause))
  930                 reg |= 0x80;
  931         else
  932                 reg &= ~0x80;
  933 
  934         /* Full duplex, but not half */
  935         reg |= XGBE_AN_CL37_FD_MASK;
  936         reg &= ~XGBE_AN_CL37_HD_MASK;
  937 
  938         axgbe_printf(2, "%s: Writing reg: 0x%x\n", __func__, reg);
  939         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
  940 
  941         /* Set up the Control register */
  942         reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
  943         axgbe_printf(2, "%s: AN_ADVERTISE reg 0x%x an_mode %d\n", __func__,
  944             reg, pdata->an_mode);
  945         reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK;
  946         reg &= ~XGBE_AN_CL37_PCS_MODE_MASK;
  947 
  948         switch (pdata->an_mode) {
  949         case XGBE_AN_MODE_CL37:
  950                 reg |= XGBE_AN_CL37_PCS_MODE_BASEX;
  951                 break;
  952         case XGBE_AN_MODE_CL37_SGMII:
  953                 reg |= XGBE_AN_CL37_PCS_MODE_SGMII;
  954                 break;
  955         default:
  956                 break;
  957         }
  958 
  959         reg |= XGBE_AN_CL37_MII_CTRL_8BIT;
  960         axgbe_printf(2, "%s: Writing reg: 0x%x\n", __func__, reg);
  961         XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
  962 
  963         axgbe_printf(2, "CL37 AN (%s) initialized\n",
  964             (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII");
  965 }
  966 
  967 static void
  968 xgbe_an73_init(struct xgbe_prv_data *pdata)
  969 {
  970         /* 
  971          * This local_phy is needed because phy-v2 alters the
  972          * advertising flag variable. so phy-v1 an_advertising is just copying
  973          */
  974         struct xgbe_phy local_phy;
  975         unsigned int reg;
  976 
  977         pdata->phy_if.phy_impl.an_advertising(pdata, &local_phy);
  978 
  979         /* Set up Advertisement register 3 first */
  980         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
  981         if (XGBE_ADV(&local_phy, 10000baseR_FEC))
  982                 reg |= 0xc000;
  983         else
  984                 reg &= ~0xc000;
  985 
  986         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, reg);
  987 
  988         /* Set up Advertisement register 2 next */
  989         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
  990         if (XGBE_ADV(&local_phy, 10000baseKR_Full))
  991                 reg |= 0x80;
  992         else
  993                 reg &= ~0x80;
  994 
  995         if (XGBE_ADV(&local_phy, 1000baseKX_Full) ||
  996             XGBE_ADV(&local_phy, 2500baseX_Full))
  997                 reg |= 0x20;
  998         else
  999                 reg &= ~0x20;
 1000 
 1001         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, reg);
 1002 
 1003         /* Set up Advertisement register 1 last */
 1004         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
 1005         if (XGBE_ADV(&local_phy, Pause))
 1006                 reg |= 0x400;
 1007         else
 1008                 reg &= ~0x400;
 1009 
 1010         if (XGBE_ADV(&local_phy, Asym_Pause))
 1011                 reg |= 0x800;
 1012         else
 1013                 reg &= ~0x800;
 1014 
 1015         /* We don't intend to perform XNP */
 1016         reg &= ~XGBE_XNP_NP_EXCHANGE;
 1017 
 1018         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
 1019 
 1020         axgbe_printf(2, "CL73 AN initialized\n");
 1021 }
 1022 
 1023 static void
 1024 xgbe_an_init(struct xgbe_prv_data *pdata)
 1025 {
 1026         /* Set up advertisement registers based on current settings */
 1027         pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata);
 1028         axgbe_printf(2, "%s: setting up an_mode %d\n", __func__, pdata->an_mode);
 1029 
 1030         switch (pdata->an_mode) {
 1031         case XGBE_AN_MODE_CL73:
 1032         case XGBE_AN_MODE_CL73_REDRV:
 1033                 xgbe_an73_init(pdata);
 1034                 break;
 1035         case XGBE_AN_MODE_CL37:
 1036         case XGBE_AN_MODE_CL37_SGMII:
 1037                 xgbe_an37_init(pdata);
 1038                 break;
 1039         default:
 1040                 break;
 1041         }
 1042 }
 1043 
 1044 static const char *
 1045 xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
 1046 {
 1047         if (pdata->tx_pause && pdata->rx_pause)
 1048                 return ("rx/tx");
 1049         else if (pdata->rx_pause)
 1050                 return ("rx");
 1051         else if (pdata->tx_pause)
 1052                 return ("tx");
 1053         else
 1054                 return ("off");
 1055 }
 1056 
 1057 static const char *
 1058 xgbe_phy_speed_string(int speed)
 1059 {
 1060         switch (speed) {
 1061         case SPEED_100:
 1062                 return ("100Mbps");
 1063         case SPEED_1000:
 1064                 return ("1Gbps");
 1065         case SPEED_2500:
 1066                 return ("2.5Gbps");
 1067         case SPEED_10000:
 1068                 return ("10Gbps");
 1069         case SPEED_UNKNOWN:
 1070                 return ("Unknown");
 1071         default:
 1072                 return ("Unsupported");
 1073         }
 1074 }
 1075 
 1076 static void
 1077 xgbe_phy_print_status(struct xgbe_prv_data *pdata)
 1078 {
 1079         if (pdata->phy.link)
 1080                 axgbe_printf(0,
 1081                     "Link is UP - %s/%s - flow control %s\n",
 1082                     xgbe_phy_speed_string(pdata->phy.speed),
 1083                     pdata->phy.duplex == DUPLEX_FULL ? "Full" : "Half",
 1084                     xgbe_phy_fc_string(pdata));
 1085         else
 1086                 axgbe_printf(0, "Link is DOWN\n");
 1087 }
 1088 
 1089 static void
 1090 xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
 1091 {
 1092         int new_state = 0;
 1093 
 1094         axgbe_printf(1, "link %d/%d tx %d/%d rx %d/%d speed %d/%d autoneg %d/%d\n",
 1095             pdata->phy_link, pdata->phy.link,
 1096             pdata->tx_pause, pdata->phy.tx_pause,
 1097             pdata->rx_pause, pdata->phy.rx_pause,
 1098             pdata->phy_speed, pdata->phy.speed,
 1099             pdata->pause_autoneg, pdata->phy.pause_autoneg);
 1100 
 1101         if (pdata->phy.link) {
 1102                 /* Flow control support */
 1103                 pdata->pause_autoneg = pdata->phy.pause_autoneg;
 1104 
 1105                 if (pdata->tx_pause != pdata->phy.tx_pause) {
 1106                         new_state = 1;
 1107                         axgbe_printf(2, "tx pause %d/%d\n", pdata->tx_pause,
 1108                             pdata->phy.tx_pause);
 1109                         pdata->tx_pause = pdata->phy.tx_pause;
 1110                         pdata->hw_if.config_tx_flow_control(pdata);
 1111                 }
 1112 
 1113                 if (pdata->rx_pause != pdata->phy.rx_pause) {
 1114                         new_state = 1;
 1115                         axgbe_printf(2, "rx pause %d/%d\n", pdata->rx_pause,
 1116                             pdata->phy.rx_pause);
 1117                         pdata->rx_pause = pdata->phy.rx_pause;
 1118                         pdata->hw_if.config_rx_flow_control(pdata);
 1119                 }
 1120 
 1121                 /* Speed support */
 1122                 if (pdata->phy_speed != pdata->phy.speed) {
 1123                         new_state = 1;
 1124                         pdata->phy_speed = pdata->phy.speed;
 1125                 }
 1126 
 1127                 if (pdata->phy_link != pdata->phy.link) {
 1128                         new_state = 1;
 1129                         pdata->phy_link = pdata->phy.link;
 1130                 }
 1131         } else if (pdata->phy_link) {
 1132                 new_state = 1;
 1133                 pdata->phy_link = 0;
 1134                 pdata->phy_speed = SPEED_UNKNOWN;
 1135         }
 1136 
 1137         axgbe_printf(2, "phy_link %d Link %d new_state %d\n", pdata->phy_link,
 1138             pdata->phy.link, new_state);
 1139 
 1140         if (new_state)
 1141                 xgbe_phy_print_status(pdata);
 1142 }
 1143 
 1144 static bool
 1145 xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
 1146 {
 1147         return (pdata->phy_if.phy_impl.valid_speed(pdata, speed));
 1148 }
 1149 
 1150 static int
 1151 xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
 1152 {
 1153         enum xgbe_mode mode;
 1154 
 1155         axgbe_printf(2, "fixed PHY configuration\n");
 1156 
 1157         /* Disable auto-negotiation */
 1158         xgbe_an_disable(pdata);
 1159 
 1160         /* Set specified mode for specified speed */
 1161         mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
 1162         switch (mode) {
 1163         case XGBE_MODE_KX_1000:
 1164         case XGBE_MODE_KX_2500:
 1165         case XGBE_MODE_KR:
 1166         case XGBE_MODE_SGMII_100:
 1167         case XGBE_MODE_SGMII_1000:
 1168         case XGBE_MODE_X:
 1169         case XGBE_MODE_SFI:
 1170                 break;
 1171         case XGBE_MODE_UNKNOWN:
 1172         default:
 1173                 return (-EINVAL);
 1174         }
 1175 
 1176         /* Validate duplex mode */
 1177         if (pdata->phy.duplex != DUPLEX_FULL)
 1178                 return (-EINVAL);
 1179 
 1180         xgbe_set_mode(pdata, mode);
 1181 
 1182         return (0);
 1183 }
 1184 
 1185 static int
 1186 __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode)
 1187 {
 1188         int ret;
 1189         unsigned int reg = 0;
 1190 
 1191         sx_xlock(&pdata->an_mutex);
 1192 
 1193         set_bit(XGBE_LINK_INIT, &pdata->dev_state);
 1194         pdata->link_check = ticks;
 1195 
 1196         ret = pdata->phy_if.phy_impl.an_config(pdata);
 1197         if (ret) {
 1198                 axgbe_error("%s: an_config fail %d\n", __func__, ret);
 1199                 goto out;
 1200         }
 1201 
 1202         if (pdata->phy.autoneg != AUTONEG_ENABLE) {
 1203                 ret = xgbe_phy_config_fixed(pdata);
 1204                 if (ret || !pdata->kr_redrv) {
 1205                         if (ret)
 1206                                 axgbe_error("%s: fix conf fail %d\n", __func__, ret);
 1207                         goto out;
 1208                 }
 1209 
 1210                 axgbe_printf(2, "AN redriver support\n");
 1211         } else
 1212                 axgbe_printf(2, "AN PHY configuration\n");
 1213 
 1214         /* Disable auto-negotiation interrupt */
 1215         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
 1216         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK);
 1217         axgbe_printf(2, "%s: set_mode %d AN int reg value 0x%x\n", __func__,
 1218             set_mode, reg);
 1219 
 1220         /* Clear any auto-negotitation interrupts */
 1221         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
 1222 
 1223         /* Start auto-negotiation in a supported mode */
 1224         if (set_mode) {
 1225                 /* Start auto-negotiation in a supported mode */
 1226                 if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
 1227                         xgbe_set_mode(pdata, XGBE_MODE_KR);
 1228                 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
 1229                         xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
 1230                 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
 1231                         xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
 1232                 } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
 1233                         xgbe_set_mode(pdata, XGBE_MODE_SFI);
 1234                 } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
 1235                         xgbe_set_mode(pdata, XGBE_MODE_X);
 1236                 } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
 1237                         xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
 1238                 } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
 1239                         xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
 1240                 } else {
 1241                         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
 1242                         ret = -EINVAL;
 1243                         goto out;
 1244                 }
 1245         }
 1246 
 1247         /* Disable and stop any in progress auto-negotiation */
 1248         xgbe_an_disable_all(pdata);
 1249 
 1250         /* Clear any auto-negotitation interrupts */
 1251         xgbe_an_clear_interrupts_all(pdata);
 1252 
 1253         pdata->an_result = XGBE_AN_READY;
 1254         pdata->an_state = XGBE_AN_READY;
 1255         pdata->kr_state = XGBE_RX_BPA;
 1256         pdata->kx_state = XGBE_RX_BPA;
 1257 
 1258         /* Re-enable auto-negotiation interrupt */
 1259         XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
 1260         reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK);
 1261 
 1262         /* Set up advertisement registers based on current settings */
 1263         xgbe_an_init(pdata);
 1264 
 1265         /* Enable and start auto-negotiation */
 1266         xgbe_an_restart(pdata);
 1267 
 1268 out:
 1269         if (ret) {
 1270                 axgbe_printf(0, "%s: set_mode %d AN int reg value 0x%x ret value %d\n",
 1271                    __func__, set_mode, reg, ret);
 1272                 set_bit(XGBE_LINK_ERR, &pdata->dev_state);
 1273         } else
 1274                 clear_bit(XGBE_LINK_ERR, &pdata->dev_state);
 1275 
 1276         sx_unlock(&pdata->an_mutex);
 1277 
 1278         return (ret);
 1279 }
 1280 
 1281 static int
 1282 xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
 1283 {
 1284         return (__xgbe_phy_config_aneg(pdata, true));
 1285 }
 1286 
 1287 static int
 1288 xgbe_phy_reconfig_aneg(struct xgbe_prv_data *pdata)
 1289 {
 1290         return (__xgbe_phy_config_aneg(pdata, false));
 1291 }
 1292 
 1293 static bool
 1294 xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
 1295 {
 1296         return (pdata->an_result == XGBE_AN_COMPLETE);
 1297 }
 1298 
 1299 static void
 1300 xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
 1301 {
 1302         unsigned long link_timeout;
 1303 
 1304         link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * hz);
 1305         if ((int)(ticks - link_timeout) > 0) {
 1306                 axgbe_printf(2, "AN link timeout\n");
 1307                 xgbe_phy_config_aneg(pdata);
 1308         }
 1309 }
 1310 
 1311 static enum xgbe_mode
 1312 xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
 1313 {
 1314         return (pdata->phy_if.phy_impl.an_outcome(pdata));
 1315 }
 1316 
 1317 static void
 1318 xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 1319 {
 1320         enum xgbe_mode mode;
 1321 
 1322         XGBE_ZERO_LP_ADV(&pdata->phy);
 1323 
 1324         if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
 1325                 mode = xgbe_cur_mode(pdata);
 1326         else
 1327                 mode = xgbe_phy_status_aneg(pdata);
 1328 
 1329         axgbe_printf(3, "%s: xgbe mode %d\n", __func__, mode);
 1330         switch (mode) {
 1331         case XGBE_MODE_SGMII_100:
 1332                 pdata->phy.speed = SPEED_100;
 1333                 break;
 1334         case XGBE_MODE_X:
 1335         case XGBE_MODE_KX_1000:
 1336         case XGBE_MODE_SGMII_1000:
 1337                 pdata->phy.speed = SPEED_1000;
 1338                 break;
 1339         case XGBE_MODE_KX_2500:
 1340                 pdata->phy.speed = SPEED_2500;
 1341                 break;
 1342         case XGBE_MODE_KR:
 1343         case XGBE_MODE_SFI:
 1344                 pdata->phy.speed = SPEED_10000;
 1345                 break;
 1346         case XGBE_MODE_UNKNOWN:
 1347         default:
 1348                 axgbe_printf(1, "%s: unknown mode\n", __func__);
 1349                 pdata->phy.speed = SPEED_UNKNOWN;
 1350         }
 1351 
 1352         pdata->phy.duplex = DUPLEX_FULL;
 1353         axgbe_printf(2, "%s: speed %d duplex %d\n", __func__, pdata->phy.speed,
 1354             pdata->phy.duplex);
 1355 
 1356         if (xgbe_set_mode(pdata, mode) && pdata->an_again)
 1357                 xgbe_phy_reconfig_aneg(pdata);
 1358 }
 1359 
 1360 static void
 1361 xgbe_phy_status(struct xgbe_prv_data *pdata)
 1362 {
 1363         bool link_aneg;
 1364         int an_restart;
 1365 
 1366         if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
 1367                 axgbe_error("%s: LINK_ERR\n", __func__);
 1368                 pdata->phy.link = 0;
 1369                 goto adjust_link;
 1370         }
 1371 
 1372         link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
 1373         axgbe_printf(3, "link_aneg - %d\n", link_aneg);
 1374 
 1375         /* Get the link status. Link status is latched low, so read
 1376          * once to clear and then read again to get current state
 1377          */
 1378         pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata,
 1379             &an_restart);
 1380 
 1381         axgbe_printf(1, "link_status returned Link:%d an_restart:%d aneg:%d\n",
 1382             pdata->phy.link, an_restart, link_aneg);
 1383 
 1384         if (an_restart) {
 1385                 xgbe_phy_config_aneg(pdata);
 1386                 return;
 1387         }
 1388 
 1389         if (pdata->phy.link) {
 1390                 axgbe_printf(2, "Link Active\n");
 1391                 if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
 1392                         axgbe_printf(1, "phy_link set check timeout\n");
 1393                         xgbe_check_link_timeout(pdata);
 1394                         return;
 1395                 }
 1396 
 1397                 axgbe_printf(2, "%s: Link write phy_status result\n", __func__);
 1398                 xgbe_phy_status_result(pdata);
 1399 
 1400                 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
 1401                         clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
 1402 
 1403         } else {
 1404                 axgbe_printf(2, "Link Deactive\n");
 1405                 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
 1406                         axgbe_printf(1, "phy_link not set check timeout\n");
 1407                         xgbe_check_link_timeout(pdata);
 1408 
 1409                         if (link_aneg) {
 1410                                 axgbe_printf(2, "link_aneg case\n");
 1411                                 return;
 1412                         }
 1413                 }
 1414 
 1415                 xgbe_phy_status_result(pdata);
 1416 
 1417         }
 1418 
 1419 adjust_link:
 1420         axgbe_printf(2, "%s: Link %d\n", __func__, pdata->phy.link);
 1421         xgbe_phy_adjust_link(pdata);
 1422 }
 1423 
 1424 static void
 1425 xgbe_phy_stop(struct xgbe_prv_data *pdata)
 1426 {
 1427         axgbe_printf(2, "stopping PHY\n");
 1428 
 1429         if (!pdata->phy_started)
 1430                 return;
 1431 
 1432         /* Indicate the PHY is down */
 1433         pdata->phy_started = 0;
 1434 
 1435         /* Disable auto-negotiation */
 1436         xgbe_an_disable_all(pdata);
 1437 
 1438         pdata->phy_if.phy_impl.stop(pdata);
 1439 
 1440         pdata->phy.link = 0;
 1441 
 1442         xgbe_phy_adjust_link(pdata);
 1443 }
 1444 
 1445 static int
 1446 xgbe_phy_start(struct xgbe_prv_data *pdata)
 1447 {
 1448         int ret;
 1449 
 1450         DBGPR("-->xgbe_phy_start\n");
 1451 
 1452         ret = pdata->phy_if.phy_impl.start(pdata);
 1453         if (ret) {
 1454                 axgbe_error("%s: impl start ret %d\n", __func__, ret);
 1455                 return (ret);
 1456         }
 1457 
 1458         /* Set initial mode - call the mode setting routines
 1459          * directly to insure we are properly configured
 1460          */
 1461         if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
 1462                 axgbe_printf(2, "%s: KR\n", __func__);
 1463                 xgbe_kr_mode(pdata);
 1464         } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
 1465                 axgbe_printf(2, "%s: KX 2500\n", __func__);
 1466                 xgbe_kx_2500_mode(pdata);
 1467         } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
 1468                 axgbe_printf(2, "%s: KX 1000\n", __func__);
 1469                 xgbe_kx_1000_mode(pdata);
 1470         } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
 1471                 axgbe_printf(2, "%s: SFI\n", __func__);
 1472                 xgbe_sfi_mode(pdata);
 1473         } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
 1474                 axgbe_printf(2, "%s: X\n", __func__);
 1475                 xgbe_x_mode(pdata);
 1476         } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
 1477                 axgbe_printf(2, "%s: SGMII 1000\n", __func__);
 1478                 xgbe_sgmii_1000_mode(pdata);
 1479         } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
 1480                 axgbe_printf(2, "%s: SGMII 100\n", __func__);
 1481                 xgbe_sgmii_100_mode(pdata);
 1482         } else {
 1483                 axgbe_error("%s: invalid mode\n", __func__);
 1484                 ret = -EINVAL;
 1485                 goto err_stop;
 1486         }
 1487 
 1488         /* Indicate the PHY is up and running */
 1489         pdata->phy_started = 1;
 1490 
 1491         /* Set up advertisement registers based on current settings */
 1492         xgbe_an_init(pdata);
 1493 
 1494         /* Enable auto-negotiation interrupts */
 1495         xgbe_an_enable_interrupts(pdata);
 1496 
 1497         ret = xgbe_phy_config_aneg(pdata);
 1498         if (ret)
 1499                 axgbe_error("%s: phy_config_aneg %d\n", __func__, ret);
 1500 
 1501         return (ret);
 1502 
 1503 err_stop:
 1504         pdata->phy_if.phy_impl.stop(pdata);
 1505 
 1506         return (ret);
 1507 }
 1508 
 1509 static int
 1510 xgbe_phy_reset(struct xgbe_prv_data *pdata)
 1511 {
 1512         int ret;
 1513 
 1514         ret = pdata->phy_if.phy_impl.reset(pdata);
 1515         if (ret) {
 1516                 axgbe_error("%s: impl phy reset %d\n", __func__, ret);
 1517                 return (ret);
 1518         }
 1519 
 1520         /* Disable auto-negotiation for now */
 1521         xgbe_an_disable_all(pdata);
 1522 
 1523         /* Clear auto-negotiation interrupts */
 1524         xgbe_an_clear_interrupts_all(pdata);
 1525 
 1526         return (0);
 1527 }
 1528 
 1529 static int
 1530 xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
 1531 {
 1532 
 1533         if (XGBE_ADV(&pdata->phy, 10000baseKR_Full))
 1534                 return (SPEED_10000);
 1535         else if (XGBE_ADV(&pdata->phy, 10000baseT_Full))
 1536                 return (SPEED_10000);
 1537         else if (XGBE_ADV(&pdata->phy, 2500baseX_Full))
 1538                 return (SPEED_2500);
 1539         else if (XGBE_ADV(&pdata->phy, 2500baseT_Full))
 1540                 return (SPEED_2500);
 1541         else if (XGBE_ADV(&pdata->phy, 1000baseKX_Full))
 1542                 return (SPEED_1000);
 1543         else if (XGBE_ADV(&pdata->phy, 1000baseT_Full))
 1544                 return (SPEED_1000);
 1545         else if (XGBE_ADV(&pdata->phy, 100baseT_Full))
 1546                 return (SPEED_100);
 1547 
 1548         return (SPEED_UNKNOWN);
 1549 }
 1550 
 1551 static void
 1552 xgbe_phy_exit(struct xgbe_prv_data *pdata)
 1553 {
 1554         pdata->phy_if.phy_impl.exit(pdata);
 1555 }
 1556 
 1557 static int
 1558 xgbe_phy_init(struct xgbe_prv_data *pdata)
 1559 {
 1560         int ret = 0;
 1561 
 1562         DBGPR("-->xgbe_phy_init\n");
 1563 
 1564         sx_init(&pdata->an_mutex, "axgbe AN lock");
 1565         pdata->mdio_mmd = MDIO_MMD_PCS;
 1566 
 1567         /* Initialize supported features */
 1568         pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
 1569                                         MDIO_PMA_10GBR_FECABLE);
 1570         pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
 1571                                MDIO_PMA_10GBR_FECABLE_ERRABLE);
 1572 
 1573         /* Setup the phy (including supported features) */
 1574         ret = pdata->phy_if.phy_impl.init(pdata);
 1575         if (ret)
 1576                 return (ret);
 1577 
 1578         /* Copy supported link modes to advertising link modes */
 1579         XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, supported);
 1580 
 1581         pdata->phy.address = 0;
 1582 
 1583         if (XGBE_ADV(&pdata->phy, Autoneg)) {
 1584                 pdata->phy.autoneg = AUTONEG_ENABLE;
 1585                 pdata->phy.speed = SPEED_UNKNOWN;
 1586                 pdata->phy.duplex = DUPLEX_UNKNOWN;
 1587         } else {
 1588                 pdata->phy.autoneg = AUTONEG_DISABLE;
 1589                 pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
 1590                 pdata->phy.duplex = DUPLEX_FULL;
 1591         }
 1592 
 1593         pdata->phy.link = 0;
 1594 
 1595         pdata->phy.pause_autoneg = pdata->pause_autoneg;
 1596         pdata->phy.tx_pause = pdata->tx_pause;
 1597         pdata->phy.rx_pause = pdata->rx_pause;
 1598 
 1599         /* Fix up Flow Control advertising */
 1600         XGBE_CLR_ADV(&pdata->phy, Pause);
 1601         XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
 1602 
 1603         if (pdata->rx_pause) {
 1604                 XGBE_SET_ADV(&pdata->phy, Pause);
 1605                 XGBE_SET_ADV(&pdata->phy, Asym_Pause);
 1606         }
 1607 
 1608         if (pdata->tx_pause) {
 1609                 if (XGBE_ADV(&pdata->phy, Asym_Pause))
 1610                         XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
 1611                 else
 1612                         XGBE_SET_ADV(&pdata->phy, Asym_Pause);
 1613         }
 1614 
 1615         return (0);
 1616 }
 1617 
 1618 void
 1619 xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
 1620 {
 1621         phy_if->phy_init        = xgbe_phy_init;
 1622         phy_if->phy_exit        = xgbe_phy_exit;
 1623 
 1624         phy_if->phy_reset       = xgbe_phy_reset;
 1625         phy_if->phy_start       = xgbe_phy_start;
 1626         phy_if->phy_stop        = xgbe_phy_stop;
 1627 
 1628         phy_if->phy_status      = xgbe_phy_status;
 1629         phy_if->phy_config_aneg = xgbe_phy_config_aneg;
 1630 
 1631         phy_if->phy_valid_speed = xgbe_phy_valid_speed;
 1632 
 1633         phy_if->an_isr          = xgbe_an_combined_isr;
 1634 }

Cache object: 488329a01c9820021962d59b2b44023a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.