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/cxgb/common/cxgb_vsc7323.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 /**************************************************************************
    3 
    4 Copyright (c) 2007, Chelsio Inc.
    5 All rights reserved.
    6 
    7 Redistribution and use in source and binary forms, with or without
    8 modification, are permitted provided that the following conditions are met:
    9 
   10  1. Redistributions of source code must retain the above copyright notice,
   11     this list of conditions and the following disclaimer.
   12 
   13  2. Neither the name of the Chelsio Corporation nor the names of its
   14     contributors may be used to endorse or promote products derived from
   15     this software without specific prior written permission.
   16 
   17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 POSSIBILITY OF SUCH DAMAGE.
   28 
   29 ***************************************************************************/
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/11.2/sys/dev/cxgb/common/cxgb_vsc7323.c 331722 2018-03-29 02:50:57Z eadler $");
   33 
   34 #include <common/cxgb_common.h>
   35 
   36 enum {
   37         ELMR_ADDR    = 0,
   38         ELMR_STAT    = 1,
   39         ELMR_DATA_LO = 2,
   40         ELMR_DATA_HI = 3,
   41 
   42         ELMR_THRES0  = 0xe000,
   43         ELMR_BW      = 0xe00c,
   44         ELMR_FIFO_SZ = 0xe00d,
   45         ELMR_STATS   = 0xf000,
   46 
   47         ELMR_MDIO_ADDR = 10
   48 };
   49 
   50 #define VSC_REG(block, subblock, reg) \
   51         ((reg) | ((subblock) << 8) | ((block) << 12))
   52 
   53 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
   54 {
   55         int ret;
   56         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
   57 
   58         ELMR_LOCK(adap);
   59         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
   60         for ( ; !ret && n; n--, vals++) {
   61                 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
   62                                 *vals & 0xffff);
   63                 if (!ret)
   64                         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
   65                                         *vals >> 16);
   66         }
   67         ELMR_UNLOCK(adap);
   68         return ret;
   69 }
   70 
   71 static int elmr_write(adapter_t *adap, int addr, u32 val)
   72 {
   73         return t3_elmr_blk_write(adap, addr, &val, 1);
   74 }
   75 
   76 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
   77 {
   78         int i, ret;
   79         unsigned int v;
   80         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
   81 
   82         ELMR_LOCK(adap);
   83 
   84         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
   85         if (ret)
   86                 goto out;
   87 
   88         for (i = 0; i < 5; i++) {
   89                 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
   90                 if (ret)
   91                         goto out;
   92                 if (v == 1)
   93                         break;
   94                 udelay(5);
   95         }
   96         if (v != 1) {
   97                 ret = -ETIMEDOUT;
   98                 goto out;
   99         }
  100 
  101         for ( ; !ret && n; n--, vals++) {
  102                 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
  103                 if (!ret) {
  104                         ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
  105                                        &v);
  106                         *vals |= v << 16;
  107                 }
  108         }
  109 out:    ELMR_UNLOCK(adap);
  110         return ret;
  111 }
  112 
  113 int t3_vsc7323_init(adapter_t *adap, int nports)
  114 {
  115         static struct addr_val_pair sys_avp[] = {
  116                 { VSC_REG(7, 15, 0xf),  2 },
  117                 { VSC_REG(7, 15, 0x19), 0xd6 },
  118                 { VSC_REG(7, 15, 7),    0xc },
  119                 { VSC_REG(7, 1, 0),     0x220 },
  120         };
  121         static struct addr_val_pair fifo_avp[] = {
  122                 { VSC_REG(2, 0, 0x2f), 0 },
  123                 { VSC_REG(2, 0, 0xf),  0xa0010291 },
  124                 { VSC_REG(2, 1, 0x2f), 1 },
  125                 { VSC_REG(2, 1, 0xf),  0xa026301 }
  126         };
  127         static struct addr_val_pair xg_avp[] = {
  128                 { VSC_REG(1, 10, 0),    0x600b },
  129                 { VSC_REG(1, 10, 1),    0x70600 }, //QUANTA = 96*1024*8/512
  130                 { VSC_REG(1, 10, 2),    0x2710 },
  131                 { VSC_REG(1, 10, 5),    0x65 },
  132                 { VSC_REG(1, 10, 7),    0x23 },
  133                 { VSC_REG(1, 10, 0x23), 0x800007bf },
  134                 { VSC_REG(1, 10, 0x23), 0x000007bf },
  135                 { VSC_REG(1, 10, 0x23), 0x800007bf },
  136                 { VSC_REG(1, 10, 0x24), 4 }
  137         };
  138 
  139         int i, ret, ing_step, egr_step, ing_bot, egr_bot;
  140 
  141         for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
  142                 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
  143                                              &sys_avp[i].val, 1)))
  144                         return ret;
  145 
  146         ing_step = 0xc0 / nports;
  147         egr_step = 0x40 / nports;
  148         ing_bot = egr_bot = 0;
  149 //      ing_wm = ing_step * 64;
  150 //      egr_wm = egr_step * 64;
  151 
  152         /* {ING,EGR}_CONTROL.CLR = 1 here */
  153         for (i = 0; i < nports; i++) {
  154                 if (
  155                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
  156                                 ((ing_bot + ing_step) << 16) | ing_bot)) ||
  157                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
  158                                 0x6000bc0)) ||
  159                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
  160                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
  161                                 ((egr_bot + egr_step) << 16) | egr_bot)) ||
  162                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
  163                                 0x2000280)) ||
  164                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
  165                         return ret;
  166                 ing_bot += ing_step;
  167                 egr_bot += egr_step;
  168         }
  169 
  170         for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
  171                 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
  172                                              &fifo_avp[i].val, 1)))
  173                         return ret;
  174 
  175         for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
  176                 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
  177                                              &xg_avp[i].val, 1)))
  178                         return ret;
  179 
  180         for (i = 0; i < nports; i++)
  181                 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
  182                     (ret = elmr_write(adap, VSC_REG(1, i, 5),
  183                                  (i << 12) | 0x63)) ||
  184                     (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
  185                     (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) ||
  186                     (ret = elmr_write(adap, ELMR_THRES0 + i, 768)))
  187                         return ret;
  188 
  189         if ((ret = elmr_write(adap, ELMR_BW, 7)))
  190                 return ret;
  191 
  192         return ret;
  193 }
  194 
  195 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
  196 {
  197         int mode, clk, r;
  198 
  199         if (speed >= 0) {
  200                 if (speed == SPEED_10)
  201                         mode = clk = 1;
  202                 else if (speed == SPEED_100)
  203                         mode = 1, clk = 2;
  204                 else if (speed == SPEED_1000)
  205                         mode = clk = 3;
  206                 else
  207                         return -EINVAL;
  208 
  209                 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
  210                                     0xa590 | (mode << 2))) ||
  211                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
  212                                     0x91 | (clk << 1))) ||
  213                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
  214                                     0x90 | (clk << 1))) ||
  215                     (r = elmr_write(adap, VSC_REG(1, port, 0),
  216                                     0xa593 | (mode << 2))))
  217                         return r;
  218         }
  219 
  220         r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
  221         if (fc & PAUSE_TX)
  222                 r |= (1 << 19);
  223         return elmr_write(adap, VSC_REG(1, port, 1), r);
  224 }
  225 
  226 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
  227 {
  228         return elmr_write(adap, VSC_REG(1, port, 2), mtu);
  229 }
  230 
  231 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
  232 {
  233         int ret;
  234 
  235         ret = elmr_write(adap, VSC_REG(1, port, 3),
  236                          (addr[0] << 16) | (addr[1] << 8) | addr[2]);
  237         if (!ret)
  238                 ret = elmr_write(adap, VSC_REG(1, port, 4),
  239                                  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
  240         return ret;
  241 }
  242 
  243 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
  244 {
  245         int ret;
  246         unsigned int v, orig;
  247 
  248         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
  249         if (!ret) {
  250                 orig = v;
  251                 if (which & MAC_DIRECTION_TX)
  252                         v |= 1;
  253                 if (which & MAC_DIRECTION_RX)
  254                         v |= 2;
  255                 if (v != orig)
  256                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
  257         }
  258         return ret;
  259 }
  260 
  261 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
  262 {
  263         int ret;
  264         unsigned int v, orig;
  265 
  266         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
  267         if (!ret) {
  268                 orig = v;
  269                 if (which & MAC_DIRECTION_TX)
  270                         v &= ~1;
  271                 if (which & MAC_DIRECTION_RX)
  272                         v &= ~2;
  273                 if (v != orig)
  274                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
  275         }
  276         return ret;
  277 }
  278 
  279 #define STATS0_START 1
  280 #define STATS1_START 0x24
  281 #define NSTATS0 (0x1d - STATS0_START + 1)
  282 #define NSTATS1 (0x2a - STATS1_START + 1)
  283 
  284 #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg)
  285 
  286 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
  287 {
  288         int ret;
  289         u64 rx_ucast, tx_ucast;
  290         u32 stats0[NSTATS0], stats1[NSTATS1];
  291 
  292         ret = t3_elmr_blk_read(mac->adapter,
  293                                ELMR_STAT(mac->ext_port, STATS0_START),
  294                                stats0, NSTATS0);
  295         if (!ret)
  296                 ret = t3_elmr_blk_read(mac->adapter,
  297                                        ELMR_STAT(mac->ext_port, STATS1_START),
  298                                        stats1, NSTATS1);
  299         if (ret)
  300                 goto out;
  301 
  302         /*
  303          * HW counts Rx/Tx unicast frames but we want all the frames.
  304          */
  305         rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
  306                    mac->stats.rx_bcast_frames;
  307         rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
  308         tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
  309                    mac->stats.tx_bcast_frames;
  310         tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
  311 
  312 #define RMON_UPDATE(mac, name, hw_stat) \
  313         mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
  314 
  315         RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
  316         RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
  317         RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
  318         RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
  319         RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
  320         RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
  321         RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
  322         RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
  323         RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
  324         RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
  325         RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
  326         RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
  327 
  328         RMON_UPDATE(mac, rx_frames_64,        stats0[17 - STATS0_START]);
  329         RMON_UPDATE(mac, rx_frames_65_127,    stats0[18 - STATS0_START]);
  330         RMON_UPDATE(mac, rx_frames_128_255,   stats0[19 - STATS0_START]);
  331         RMON_UPDATE(mac, rx_frames_256_511,   stats0[20 - STATS0_START]);
  332         RMON_UPDATE(mac, rx_frames_512_1023,  stats0[21 - STATS0_START]);
  333         RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
  334         RMON_UPDATE(mac, rx_frames_1519_max,  stats0[23 - STATS0_START]);
  335 
  336         RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
  337         RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
  338         RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
  339         RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
  340         RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
  341         RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
  342         RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
  343 
  344         RMON_UPDATE(mac, tx_underrun, 0);
  345 
  346         RMON_UPDATE(mac, tx_frames_64,        stats1[36 - STATS1_START]);
  347         RMON_UPDATE(mac, tx_frames_65_127,    stats1[37 - STATS1_START]);
  348         RMON_UPDATE(mac, tx_frames_128_255,   stats1[38 - STATS1_START]);
  349         RMON_UPDATE(mac, tx_frames_256_511,   stats1[39 - STATS1_START]);
  350         RMON_UPDATE(mac, tx_frames_512_1023,  stats1[40 - STATS1_START]);
  351         RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
  352         RMON_UPDATE(mac, tx_frames_1519_max,  stats1[42 - STATS1_START]);
  353 
  354 #undef RMON_UPDATE
  355 
  356         mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
  357                                mac->stats.rx_bcast_frames;
  358         mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
  359                                mac->stats.tx_bcast_frames;
  360 out:    return &mac->stats;
  361 }

Cache object: 85b23538b9374417ba08b072f10dcfc2


[ 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.