~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/bnx2x/bnx2x_ethtool.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* bnx2x_ethtool.c: Broadcom Everest network driver.
2
2
 *
3
 
 * Copyright (c) 2007-2010 Broadcom Corporation
 
3
 * Copyright (c) 2007-2011 Broadcom Corporation
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License as published by
167
167
{
168
168
        struct bnx2x *bp = netdev_priv(dev);
169
169
        int cfg_idx = bnx2x_get_link_cfg_idx(bp);
 
170
 
170
171
        /* Dual Media boards present all available port types */
171
172
        cmd->supported = bp->port.supported[cfg_idx] |
172
173
                (bp->port.supported[cfg_idx ^ 1] &
176
177
        if ((bp->state == BNX2X_STATE_OPEN) &&
177
178
            !(bp->flags & MF_FUNC_DIS) &&
178
179
            (bp->link_vars.link_up)) {
179
 
                cmd->speed = bp->link_vars.line_speed;
 
180
                ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
180
181
                cmd->duplex = bp->link_vars.duplex;
181
182
        } else {
182
 
 
183
 
                cmd->speed = bp->link_params.req_line_speed[cfg_idx];
 
183
                ethtool_cmd_speed_set(
 
184
                        cmd, bp->link_params.req_line_speed[cfg_idx]);
184
185
                cmd->duplex = bp->link_params.req_duplex[cfg_idx];
185
186
        }
186
187
 
187
188
        if (IS_MF(bp))
188
 
                cmd->speed = bnx2x_get_mf_speed(bp);
 
189
                ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
189
190
 
190
191
        if (bp->port.supported[cfg_idx] & SUPPORTED_TP)
191
192
                cmd->port = PORT_TP;
206
207
        cmd->maxrxpkt = 0;
207
208
 
208
209
        DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
209
 
           DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %d\n"
 
210
           DP_LEVEL "  supported 0x%x  advertising 0x%x  speed %u\n"
210
211
           DP_LEVEL "  duplex %d  port %d  phy_address %d  transceiver %d\n"
211
212
           DP_LEVEL "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
212
 
           cmd->cmd, cmd->supported, cmd->advertising, cmd->speed,
 
213
           cmd->cmd, cmd->supported, cmd->advertising,
 
214
           ethtool_cmd_speed(cmd),
213
215
           cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
214
216
           cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
215
217
 
226
228
                return 0;
227
229
 
228
230
        DP(NETIF_MSG_LINK, "ethtool_cmd: cmd %d\n"
229
 
           "  supported 0x%x  advertising 0x%x  speed %d speed_hi %d\n"
 
231
           "  supported 0x%x  advertising 0x%x  speed %u\n"
230
232
           "  duplex %d  port %d  phy_address %d  transceiver %d\n"
231
233
           "  autoneg %d  maxtxpkt %d  maxrxpkt %d\n",
232
 
           cmd->cmd, cmd->supported, cmd->advertising, cmd->speed,
233
 
           cmd->speed_hi,
 
234
           cmd->cmd, cmd->supported, cmd->advertising,
 
235
           ethtool_cmd_speed(cmd),
234
236
           cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
235
237
           cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
236
238
 
237
 
        speed = cmd->speed;
238
 
        speed |= (cmd->speed_hi << 16);
 
239
        speed = ethtool_cmd_speed(cmd);
239
240
 
240
241
        if (IS_MF_SI(bp)) {
241
242
                u32 part;
439
440
                        break;
440
441
 
441
442
                default:
442
 
                        DP(NETIF_MSG_LINK, "Unsupported speed %d\n", speed);
 
443
                        DP(NETIF_MSG_LINK, "Unsupported speed %u\n", speed);
443
444
                        return -EINVAL;
444
445
                }
445
446
 
1219
1220
        }
1220
1221
 
1221
1222
        if ((ering->rx_pending > MAX_RX_AVAIL) ||
1222
 
            (ering->rx_pending < MIN_RX_AVAIL) ||
 
1223
            (ering->rx_pending < (bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
 
1224
                                                    MIN_RX_SIZE_TPA)) ||
1223
1225
            (ering->tx_pending > MAX_TX_AVAIL) ||
1224
1226
            (ering->tx_pending <= MAX_SKB_FRAGS + 4))
1225
1227
                return -EINVAL;
1299
1301
        return 0;
1300
1302
}
1301
1303
 
1302
 
static int bnx2x_set_flags(struct net_device *dev, u32 data)
1303
 
{
1304
 
        struct bnx2x *bp = netdev_priv(dev);
1305
 
        int changed = 0;
1306
 
        int rc = 0;
1307
 
 
1308
 
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
1309
 
                printk(KERN_ERR "Handling parity error recovery. Try again later\n");
1310
 
                return -EAGAIN;
1311
 
        }
1312
 
 
1313
 
        if (!(data & ETH_FLAG_RXVLAN))
1314
 
                return -EINVAL;
1315
 
 
1316
 
        if ((data & ETH_FLAG_LRO) && bp->rx_csum && bp->disable_tpa)
1317
 
                return -EINVAL;
1318
 
 
1319
 
        rc = ethtool_op_set_flags(dev, data, ETH_FLAG_LRO | ETH_FLAG_RXVLAN |
1320
 
                                        ETH_FLAG_TXVLAN | ETH_FLAG_RXHASH);
1321
 
        if (rc)
1322
 
                return rc;
1323
 
 
1324
 
        /* TPA requires Rx CSUM offloading */
1325
 
        if ((data & ETH_FLAG_LRO) && bp->rx_csum) {
1326
 
                if (!(bp->flags & TPA_ENABLE_FLAG)) {
1327
 
                        bp->flags |= TPA_ENABLE_FLAG;
1328
 
                        changed = 1;
1329
 
                }
1330
 
        } else if (bp->flags & TPA_ENABLE_FLAG) {
1331
 
                dev->features &= ~NETIF_F_LRO;
1332
 
                bp->flags &= ~TPA_ENABLE_FLAG;
1333
 
                changed = 1;
1334
 
        }
1335
 
 
1336
 
        if (changed && netif_running(dev)) {
1337
 
                bnx2x_nic_unload(bp, UNLOAD_NORMAL);
1338
 
                rc = bnx2x_nic_load(bp, LOAD_NORMAL);
1339
 
        }
1340
 
 
1341
 
        return rc;
1342
 
}
1343
 
 
1344
 
static u32 bnx2x_get_rx_csum(struct net_device *dev)
1345
 
{
1346
 
        struct bnx2x *bp = netdev_priv(dev);
1347
 
 
1348
 
        return bp->rx_csum;
1349
 
}
1350
 
 
1351
 
static int bnx2x_set_rx_csum(struct net_device *dev, u32 data)
1352
 
{
1353
 
        struct bnx2x *bp = netdev_priv(dev);
1354
 
        int rc = 0;
1355
 
 
1356
 
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
1357
 
                printk(KERN_ERR "Handling parity error recovery. Try again later\n");
1358
 
                return -EAGAIN;
1359
 
        }
1360
 
 
1361
 
        bp->rx_csum = data;
1362
 
 
1363
 
        /* Disable TPA, when Rx CSUM is disabled. Otherwise all
1364
 
           TPA'ed packets will be discarded due to wrong TCP CSUM */
1365
 
        if (!data) {
1366
 
                u32 flags = ethtool_op_get_flags(dev);
1367
 
 
1368
 
                rc = bnx2x_set_flags(dev, (flags & ~ETH_FLAG_LRO));
1369
 
        }
1370
 
 
1371
 
        return rc;
1372
 
}
1373
 
 
1374
 
static int bnx2x_set_tso(struct net_device *dev, u32 data)
1375
 
{
1376
 
        if (data) {
1377
 
                dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
1378
 
                dev->features |= NETIF_F_TSO6;
1379
 
        } else {
1380
 
                dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
1381
 
                dev->features &= ~NETIF_F_TSO6;
1382
 
        }
1383
 
 
1384
 
        return 0;
1385
 
}
1386
 
 
1387
1304
static const struct {
1388
1305
        char string[ETH_GSTRING_LEN];
1389
1306
} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = {
1617
1534
        /* prepare the loopback packet */
1618
1535
        pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ?
1619
1536
                     bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN);
1620
 
        skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
 
1537
        skb = netdev_alloc_skb(bp->dev, fp_rx->rx_buf_size);
1621
1538
        if (!skb) {
1622
1539
                rc = -ENOMEM;
1623
1540
                goto test_loopback_exit;
2097
2014
        }
2098
2015
}
2099
2016
 
2100
 
static int bnx2x_phys_id(struct net_device *dev, u32 data)
 
2017
static int bnx2x_set_phys_id(struct net_device *dev,
 
2018
                             enum ethtool_phys_id_state state)
2101
2019
{
2102
2020
        struct bnx2x *bp = netdev_priv(dev);
2103
 
        int i;
2104
2021
 
2105
2022
        if (!netif_running(dev))
2106
 
                return 0;
 
2023
                return -EAGAIN;
2107
2024
 
2108
2025
        if (!bp->port.pmf)
2109
 
                return 0;
2110
 
 
2111
 
        if (data == 0)
2112
 
                data = 2;
2113
 
 
2114
 
        for (i = 0; i < (data * 2); i++) {
2115
 
                if ((i % 2) == 0)
2116
 
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
2117
 
                                      LED_MODE_OPER, SPEED_1000);
2118
 
                else
2119
 
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
2120
 
                                      LED_MODE_OFF, 0);
2121
 
 
2122
 
                msleep_interruptible(500);
2123
 
                if (signal_pending(current))
2124
 
                        break;
2125
 
        }
2126
 
 
2127
 
        if (bp->link_vars.link_up)
2128
 
                bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
 
2026
                return -EOPNOTSUPP;
 
2027
 
 
2028
        switch (state) {
 
2029
        case ETHTOOL_ID_ACTIVE:
 
2030
                return 1;       /* cycle on/off once per second */
 
2031
 
 
2032
        case ETHTOOL_ID_ON:
 
2033
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
 
2034
                              LED_MODE_ON, SPEED_1000);
 
2035
                break;
 
2036
 
 
2037
        case ETHTOOL_ID_OFF:
 
2038
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
 
2039
                              LED_MODE_FRONT_PANEL_OFF, 0);
 
2040
 
 
2041
                break;
 
2042
 
 
2043
        case ETHTOOL_ID_INACTIVE:
 
2044
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
 
2045
                              LED_MODE_OPER,
2129
2046
                              bp->link_vars.line_speed);
2130
 
 
 
2047
        }
 
2048
 
 
2049
        return 0;
 
2050
}
 
2051
 
 
2052
static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
 
2053
                           void *rules __always_unused)
 
2054
{
 
2055
        struct bnx2x *bp = netdev_priv(dev);
 
2056
 
 
2057
        switch (info->cmd) {
 
2058
        case ETHTOOL_GRXRINGS:
 
2059
                info->data = BNX2X_NUM_ETH_QUEUES(bp);
 
2060
                return 0;
 
2061
 
 
2062
        default:
 
2063
                return -EOPNOTSUPP;
 
2064
        }
 
2065
}
 
2066
 
 
2067
static int bnx2x_get_rxfh_indir(struct net_device *dev,
 
2068
                                struct ethtool_rxfh_indir *indir)
 
2069
{
 
2070
        struct bnx2x *bp = netdev_priv(dev);
 
2071
        size_t copy_size =
 
2072
                min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
 
2073
 
 
2074
        if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 
2075
                return -EOPNOTSUPP;
 
2076
 
 
2077
        indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
 
2078
        memcpy(indir->ring_index, bp->rx_indir_table,
 
2079
               copy_size * sizeof(bp->rx_indir_table[0]));
 
2080
        return 0;
 
2081
}
 
2082
 
 
2083
static int bnx2x_set_rxfh_indir(struct net_device *dev,
 
2084
                                const struct ethtool_rxfh_indir *indir)
 
2085
{
 
2086
        struct bnx2x *bp = netdev_priv(dev);
 
2087
        size_t i;
 
2088
 
 
2089
        if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 
2090
                return -EOPNOTSUPP;
 
2091
 
 
2092
        /* Validate size and indices */
 
2093
        if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
 
2094
                return -EINVAL;
 
2095
        for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
 
2096
                if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
 
2097
                        return -EINVAL;
 
2098
 
 
2099
        memcpy(bp->rx_indir_table, indir->ring_index,
 
2100
               indir->size * sizeof(bp->rx_indir_table[0]));
 
2101
        bnx2x_push_indir_table(bp);
2131
2102
        return 0;
2132
2103
}
2133
2104
 
2152
2123
        .set_ringparam          = bnx2x_set_ringparam,
2153
2124
        .get_pauseparam         = bnx2x_get_pauseparam,
2154
2125
        .set_pauseparam         = bnx2x_set_pauseparam,
2155
 
        .get_rx_csum            = bnx2x_get_rx_csum,
2156
 
        .set_rx_csum            = bnx2x_set_rx_csum,
2157
 
        .get_tx_csum            = ethtool_op_get_tx_csum,
2158
 
        .set_tx_csum            = ethtool_op_set_tx_hw_csum,
2159
 
        .set_flags              = bnx2x_set_flags,
2160
 
        .get_flags              = ethtool_op_get_flags,
2161
 
        .get_sg                 = ethtool_op_get_sg,
2162
 
        .set_sg                 = ethtool_op_set_sg,
2163
 
        .get_tso                = ethtool_op_get_tso,
2164
 
        .set_tso                = bnx2x_set_tso,
2165
2126
        .self_test              = bnx2x_self_test,
2166
2127
        .get_sset_count         = bnx2x_get_sset_count,
2167
2128
        .get_strings            = bnx2x_get_strings,
2168
 
        .phys_id                = bnx2x_phys_id,
 
2129
        .set_phys_id            = bnx2x_set_phys_id,
2169
2130
        .get_ethtool_stats      = bnx2x_get_ethtool_stats,
 
2131
        .get_rxnfc              = bnx2x_get_rxnfc,
 
2132
        .get_rxfh_indir         = bnx2x_get_rxfh_indir,
 
2133
        .set_rxfh_indir         = bnx2x_set_rxfh_indir,
2170
2134
};
2171
2135
 
2172
2136
void bnx2x_set_ethtool_ops(struct net_device *netdev)