openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

port.c (10420B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        bcmxdiag/port.c
      8  * Purpose:     Implement bcmx port command
      9  * Requires:    
     10  */
     11 
     12 #include <bcm/port.h>
     13 #include <bcm/error.h>
     14 #include <shared/bsl.h>
     15 #include <bcmx/port.h>
     16 #include <bcmx/bcmx.h>
     17 
     18 #include <appl/diag/shell.h>
     19 #include <appl/diag/system.h>
     20 #include <appl/diag/parse.h>
     21 
     22 #include "bcmx.h"
     23 #include <appl/diag/diag.h>
     24 
     25 #define PCMD_DONE(rv) cmd_rv = (rv); goto done
     26 
     27 char bcmx_cmd_port_usage[] =
     28     "    port [-b] <uport-list> [opts]    - List (briefly) port properties\n"
     29     "    port <uport-list> [opts]         - Set options indicated\n"
     30 #ifndef COMPILER_STRING_CONST_LIMIT
     31     "    Options include:\n"
     32     "        AutoNeg[=on|off]                 LinkScan[=on|off|hw|sw]\n"
     33     "        SPeed[=10|100|1000]              FullDuplex[=true|false]\n"
     34     "        TxPAUse[=on|off]                 RxPAUse[=on|off]\n"
     35     "        STationADdr[=<macaddr>]          LeaRN[=<learnmode>]\n"
     36     "        DIScard[=none|untag|all]         VlanFilter[=on|off]\n"
     37     "        UTPRIrity[=<pri>]                UTVlan[=<vid>]\n"
     38     "        PortFilterMode[=<value>]         PHymaster[=Master|Slave|Auto]\n"
     39     "Speed, duplex, pause are the ADVERTISED or FORCED according to autoneg.\n"
     40     "Speed of zero indicates maximum speed.\n"
     41     "LinkScan enables automatic scanning for link changes.\n"
     42     "VlanFilter drops input packets that are not tagged with a valid VLAN\n"
     43     "Priority sets the priority for untagged packets.\n"
     44     "PortFilterMode takes a value 0/1/2 for mode A/B/C (see register ref).\n"
     45     "<vid> is valid VLAN identifier.  <pri> is a value from 0 to 7.\n"
     46     "<learnmode> flag: bit 0 --> enable learning.  \n"
     47     "    bit 1 --> forward to CPU.   bit 2 --> switch packet\n"
     48 #endif
     49     ;
     50 
     51 /* Note that 'unit' is left over from the bcm layer.  It should be ignored */
     52 cmd_result_t
     53 bcmx_cmd_port(int unit, args_t *args)
     54 {
     55     char *ch;
     56     bcmx_lplist_t ports;
     57     bcm_port_info_t given;
     58     bcm_port_info_t info;
     59     bcm_port_info_t *info_p;
     60     bcm_port_info_t *port_info = NULL;
     61     int rv;
     62     int count;
     63     bcmx_lport_t lport;
     64     int brief = FALSE;
     65     parse_table_t pt;
     66     uint32 seen = 0;
     67 #if  defined(BCM_ESW_SUPPORT)
     68     uint32 port_flags;
     69 #endif /*  define (BCM_ESW_SUPPORT) */
     70     uint32 parsed = 0;
     71     char uport_str[BCMX_UPORT_STR_LENGTH_DEFAULT];
     72     bcmx_uport_t uport;
     73     cmd_result_t cmd_rv = CMD_OK;
     74 
     75     if ((ch = ARG_GET(args)) == NULL) {
     76         return(CMD_USAGE);
     77     }
     78 
     79     if (!strcmp("-b", ch)) {
     80         brief = TRUE;
     81         if ((ch = ARG_GET(args)) == NULL) {
     82             return(CMD_USAGE);
     83         }
     84     }
     85 
     86     bcmx_lplist_init(&ports, 0, 0);
     87 
     88     if (bcmx_lplist_parse(&ports, ch) < 0) {
     89         cli_out("%s: Error: could not parse portlist: %s\n",
     90                 ARG_CMD(args), ch);
     91         PCMD_DONE(CMD_FAIL);
     92     }
     93 
     94     if (ports.lp_last < 0) {
     95         cli_out("No ports specified.\n");
     96         PCMD_DONE(CMD_FAIL);
     97     }
     98 
     99     if (ARG_CNT(args) == 0) {
    100         seen = BCM_PORT_ATTR_ALL_MASK & ~BCM_PORT_ATTR_RATE_MASK;
    101     } else { /* Some arguments given..... */
    102         /*
    103          * Parse the arguments.  Determine which ones were actually given.
    104          */
    105         parse_table_init(unit, &pt);
    106 
    107 #if defined(BCM_ESW_SUPPORT)
    108         port_parse_setup(0, &pt, &given);
    109 #endif
    110         
    111         if (parse_arg_eq(args, &pt) < 0) {
    112             parse_arg_eq_done(&pt);
    113             PCMD_DONE(CMD_USAGE);
    114         }
    115 
    116         if (ARG_CNT(args) > 0) {
    117             cli_out("%s: Unknown argument %s\n",
    118                     ARG_CMD(args), ARG_CUR(args));
    119             parse_arg_eq_done(&pt);
    120             PCMD_DONE(CMD_FAIL);
    121         }
    122 
    123         /*
    124          * Find out what parameters specified.  Record values specified.
    125          */
    126 #if defined(BCM_ESW_SUPPORT)
    127         port_parse_mask_get(&pt, &seen, &parsed);
    128 #endif
    129         parse_arg_eq_done(&pt);
    130 
    131     }
    132 
    133     if (seen && parsed) {
    134         cli_out("%s: Cannot get and set port properties in one command\n",
    135                 ARG_CMD(args));
    136         PCMD_DONE(CMD_FAIL);
    137     } else if (seen) { /* Show selected information */
    138         bcm_port_config_t config;
    139         int bcm_unit, bcm_port;
    140 
    141         /****************************************************************
    142          * DISPLAY PORT INFO
    143  */
    144         if (brief) {
    145             cli_out("  Uport\n");
    146 #if defined(BCM_ESW_SUPPORT)
    147            /* Coverity
    148             * The comment at the top of this function says,
    149             * ignore unit number. -1 is not supposed to be passed
    150             * to this function, since the function accesses an array
    151             * with the passed unit number. This function is also
    152             * called from many other places but with valid unit number.
    153             * I dont want to modify the functionality of the following f(x).
    154             * Since this call with -1 is from bcmx,
    155             * I am choosing to ignore this coverity error.
    156             */
    157             /* coverity[negative_returns] */
    158             brief_port_info_header(-1);
    159 #endif
    160         } else {
    161             cli_out("Uport Status (* indicates PHY link up)\n");
    162         }
    163 
    164         BCMX_LPLIST_ITER(ports, lport, count) {
    165             uport = BCMX_LPORT_TO_UPORT(lport);
    166             bcmx_uport_to_str(uport, uport_str, BCMX_UPORT_STR_LENGTH_DEFAULT);
    167             bcmx_lport_to_unit_port(lport, &bcm_unit, &bcm_port);
    168             rv = bcm_port_config_get(bcm_unit, &config);
    169 
    170             if (BCM_FAILURE(rv)) {
    171                 cli_out("%s: Could not get port config information: %s\n",
    172                         ARG_CMD(args), bcm_errmsg(rv));
    173                 PCMD_DONE(CMD_FAIL);
    174             }
    175 
    176             if (BCM_PBMP_MEMBER(config.cpu, bcm_port)) {
    177                 if (brief) {
    178                     cli_out("%7s  up     CPU port for unit %d\n",
    179                             uport_str, bcm_unit);
    180                 } else {
    181                     cli_out(" *%s CPU port for unit %d\n",
    182                             uport_str, bcm_unit);
    183                 }
    184                 continue;
    185             }
    186 
    187 #if defined(BCM_ESW_SUPPORT)
    188             port_flags = seen;
    189             port_info_init(-1, lport, &info, port_flags);
    190 #endif /*  define (BCM_ESW_SUPPORT) */
    191             rv = bcmx_port_selective_get(lport, &info);
    192             if (BCM_FAILURE(rv)) {
    193                 cli_out("%s: Could not get port %s information: %s\n",
    194                         ARG_CMD(args), uport_str, bcm_errmsg(rv));
    195                 PCMD_DONE(CMD_FAIL);
    196             }
    197 
    198             if (brief) {
    199 #if defined(BCM_ESW_SUPPORT)
    200 #if defined(BCM_TOMAHAWK_SUPPORT)
    201                 esw_brief_port_info(unit, lport, &info, port_flags);
    202 #else
    203                 brief_port_info(unit, lport, &info, port_flags);
    204 #endif
    205 #endif
    206             } else {
    207 #if defined(BCM_ESW_SUPPORT)
    208                 disp_port_info(bcm_unit,uport_str, bcm_port, &info, 0, port_flags);
    209 #endif
    210            }            
    211         }
    212         PCMD_DONE(CMD_OK);
    213     }
    214 
    215     /****************************************************************
    216      *
    217      * SET PORT INFO
    218      *     Allocate all the info structures
    219      *     Get the info for all the ports listed
    220      *     Adjust the structures according to input
    221      *     Write all the data back at once
    222      *
    223      * After allocating ports, make sure to goto done on error.
    224  */
    225 
    226     if (parsed & BCM_PORT_ATTR_LINKSCAN_MASK) {
    227         /* Map ON --> S/W, OFF--> None */
    228         if (given.linkscan > 2) {
    229             given.linkscan -= 3;
    230         }
    231     }
    232 
    233     port_info = sal_alloc((ports.lp_last+1) * sizeof(bcm_port_info_t),
    234                           "bcmx_port");
    235     if (!port_info) {
    236         cli_out("Could not allocate enough memory for %d ports\n",
    237                 (ports.lp_last+1));
    238         PCMD_DONE(CMD_FAIL);
    239     }
    240 
    241     /* Get and adjust the information for the selected ports */
    242     BCMX_LPLIST_ITER(ports, lport, count) {
    243         info_p = &port_info[count];
    244 #if defined(BCM_ESW_SUPPORT)
    245         port_info_init(-1, lport, info_p, parsed);
    246 #endif
    247 
    248         rv = bcmx_port_selective_get(lport, info_p);
    249         if (BCM_FAILURE(rv)) {
    250             cli_out("%s: ERROR: port info get for port %s returned %s\n",
    251                     ARG_CMD(args), bcmx_lport_to_uport_str(lport),
    252                     bcm_errmsg(rv));
    253             PCMD_DONE(CMD_FAIL);
    254         }
    255     }
    256 
    257     BCMX_LPLIST_ITER(ports, lport, count) {
    258         info_p = &port_info[count];
    259         /* Get max speed and abilities for the port */
    260         if ((rv = bcmx_port_speed_max(lport, &given.speed_max)) < 0) {
    261             cli_out("port parse: Could not get port %s max speed: %s\n",
    262                     bcmx_lport_to_uport_str(lport), bcm_errmsg(rv));
    263             cmd_rv = CMD_FAIL;
    264             continue;
    265         }
    266         if ((rv = bcmx_port_speed_max(lport, &given.speed)) < 0) {
    267             cli_out("port parse: Could not get port %s peed: %s\n",
    268                     bcmx_lport_to_uport_str(lport), bcm_errmsg(rv));
    269             cmd_rv = CMD_FAIL;
    270             continue;
    271         }
    272         if ((rv = bcmx_port_ability_get(lport, &given.ability)) < 0) {
    273             cli_out("port parse: Could not get port %s ability: %s\n",
    274                     bcmx_lport_to_uport_str(lport), bcm_errmsg(rv));
    275             cmd_rv = CMD_FAIL;
    276             continue;
    277         }
    278 #if defined(BCM_ESW_SUPPORT)
    279         rv = port_parse_port_info_set(parsed, &given, info_p);
    280         if (BCM_FAILURE(rv)) {
    281             cli_out("%s: Error: Could not parse port %s info: %s\n",
    282                     ARG_CMD(args), bcmx_lport_to_uport_str(lport),
    283                     bcm_errmsg(rv));
    284             cmd_rv = CMD_FAIL;
    285             continue;
    286         }
    287 #endif
    288         
    289         /* If AN is on, do not set speed, duplex, pause */
    290         if (info_p->autoneg) {
    291             info_p->action_mask &= ~(BCM_PORT_ATTR_SPEED_MASK |
    292                   BCM_PORT_ATTR_DUPLEX_MASK | BCM_PORT_ATTR_PAUSE_MASK);
    293         }
    294 
    295         rv = bcmx_port_selective_set(lport, info_p);
    296         if (BCM_FAILURE(rv)) {
    297             cli_out("%s: ERROR: port info get for port %s returned %s\n",
    298                     ARG_CMD(args), bcmx_lport_to_uport_str(lport),
    299                     bcm_errmsg(rv));
    300             cmd_rv = CMD_FAIL;
    301             break;
    302         }
    303     }
    304 
    305 done:
    306     bcmx_lplist_free(&ports);
    307     if (port_info) {
    308         sal_free(port_info);
    309     }
    310     return cmd_rv;
    311 }
    312