1 /* 2 * QLogic qlcnic NIC Driver 3 * Copyright (c) 2009-2013 QLogic Corporation 4 * 5 * See LICENSE.qlcnic for copyright and licensing details. 6 */ 7 8 #include <linux/types.h> 9 #include <linux/delay.h> 10 #include <linux/pci.h> 11 #include <linux/io.h> 12 #include <linux/netdevice.h> 13 #include <linux/ethtool.h> 14 15 #include "qlcnic.h" 16 17 struct qlcnic_stats { 18 char stat_string[ETH_GSTRING_LEN]; 19 int sizeof_stat; 20 int stat_offset; 21 }; 22 23 #define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m) 24 #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m) 25 static const u32 qlcnic_fw_dump_level[] = { 26 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff 27 }; 28 29 static const struct qlcnic_stats qlcnic_gstrings_stats[] = { 30 {"xmit_called", QLC_SIZEOF(stats.xmitcalled), 31 QLC_OFF(stats.xmitcalled)}, 32 {"xmit_finished", QLC_SIZEOF(stats.xmitfinished), 33 QLC_OFF(stats.xmitfinished)}, 34 {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, 35 {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, 36 {"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, 37 {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, 38 {"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)}, 39 {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, 40 {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, 41 {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, 42 {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, 43 {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, 44 {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, 45 {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), 46 QLC_OFF(stats.skb_alloc_failure)}, 47 {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, 48 {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), 49 QLC_OFF(stats.rx_dma_map_error)}, 50 {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error), 51 QLC_OFF(stats.tx_dma_map_error)}, 52 {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun), 53 QLC_OFF(stats.mac_filter_limit_overrun)}, 54 {"spurious intr", QLC_SIZEOF(stats.spurious_intr), 55 QLC_OFF(stats.spurious_intr)}, 56 57 }; 58 59 static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { 60 "rx unicast frames", 61 "rx multicast frames", 62 "rx broadcast frames", 63 "rx dropped frames", 64 "rx errors", 65 "rx local frames", 66 "rx numbytes", 67 "tx unicast frames", 68 "tx multicast frames", 69 "tx broadcast frames", 70 "tx dropped frames", 71 "tx errors", 72 "tx local frames", 73 "tx numbytes", 74 }; 75 76 static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = { 77 "ctx_tx_bytes", 78 "ctx_tx_pkts", 79 "ctx_tx_errors", 80 "ctx_tx_dropped_pkts", 81 "ctx_tx_num_buffers", 82 }; 83 84 static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = { 85 "mac_tx_frames", 86 "mac_tx_bytes", 87 "mac_tx_mcast_pkts", 88 "mac_tx_bcast_pkts", 89 "mac_tx_pause_cnt", 90 "mac_tx_ctrl_pkt", 91 "mac_tx_lt_64b_pkts", 92 "mac_tx_lt_127b_pkts", 93 "mac_tx_lt_255b_pkts", 94 "mac_tx_lt_511b_pkts", 95 "mac_tx_lt_1023b_pkts", 96 "mac_tx_lt_1518b_pkts", 97 "mac_tx_gt_1518b_pkts", 98 "mac_rx_frames", 99 "mac_rx_bytes", 100 "mac_rx_mcast_pkts", 101 "mac_rx_bcast_pkts", 102 "mac_rx_pause_cnt", 103 "mac_rx_ctrl_pkt", 104 "mac_rx_lt_64b_pkts", 105 "mac_rx_lt_127b_pkts", 106 "mac_rx_lt_255b_pkts", 107 "mac_rx_lt_511b_pkts", 108 "mac_rx_lt_1023b_pkts", 109 "mac_rx_lt_1518b_pkts", 110 "mac_rx_gt_1518b_pkts", 111 "mac_rx_length_error", 112 "mac_rx_length_small", 113 "mac_rx_length_large", 114 "mac_rx_jabber", 115 "mac_rx_dropped", 116 "mac_crc_error", 117 "mac_align_error", 118 "eswitch_frames", 119 "eswitch_bytes", 120 "eswitch_multicast_frames", 121 "eswitch_broadcast_frames", 122 "eswitch_unicast_frames", 123 "eswitch_error_free_frames", 124 "eswitch_error_free_bytes", 125 }; 126 127 #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) 128 static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { 129 "ctx_rx_bytes", 130 "ctx_rx_pkts", 131 "ctx_lro_pkt_cnt", 132 "ctx_ip_csum_error", 133 "ctx_rx_pkts_wo_ctx", 134 "ctx_rx_pkts_drop_wo_sds_on_card", 135 "ctx_rx_pkts_drop_wo_sds_on_host", 136 "ctx_rx_osized_pkts", 137 "ctx_rx_pkts_dropped_wo_rds", 138 "ctx_rx_unexpected_mcast_pkts", 139 "ctx_invalid_mac_address", 140 "ctx_rx_rds_ring_prim_attempted", 141 "ctx_rx_rds_ring_prim_success", 142 "ctx_num_lro_flows_added", 143 "ctx_num_lro_flows_removed", 144 "ctx_num_lro_flows_active", 145 "ctx_pkts_dropped_unknown", 146 }; 147 148 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { 149 "Register_Test_on_offline", 150 "Link_Test_on_offline", 151 "Interrupt_Test_offline", 152 "Internal_Loopback_offline", 153 "External_Loopback_offline", 154 "EEPROM_Test_offline" 155 }; 156 157 #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) 158 159 static inline int qlcnic_82xx_statistics(void) 160 { 161 return ARRAY_SIZE(qlcnic_device_gstrings_stats) + 162 ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); 163 } 164 165 static inline int qlcnic_83xx_statistics(void) 166 { 167 return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) + 168 ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) + 169 ARRAY_SIZE(qlcnic_83xx_rx_stats_strings); 170 } 171 172 static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter) 173 { 174 if (qlcnic_82xx_check(adapter)) 175 return qlcnic_82xx_statistics(); 176 else if (qlcnic_83xx_check(adapter)) 177 return qlcnic_83xx_statistics(); 178 else 179 return -1; 180 } 181 182 #define QLCNIC_RING_REGS_COUNT 20 183 #define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32)) 184 #define QLCNIC_MAX_EEPROM_LEN 1024 185 186 static const u32 diag_registers[] = { 187 QLCNIC_CMDPEG_STATE, 188 QLCNIC_RCVPEG_STATE, 189 QLCNIC_FW_CAPABILITIES, 190 QLCNIC_CRB_DRV_ACTIVE, 191 QLCNIC_CRB_DEV_STATE, 192 QLCNIC_CRB_DRV_STATE, 193 QLCNIC_CRB_DRV_SCRATCH, 194 QLCNIC_CRB_DEV_PARTITION_INFO, 195 QLCNIC_CRB_DRV_IDC_VER, 196 QLCNIC_PEG_ALIVE_COUNTER, 197 QLCNIC_PEG_HALT_STATUS1, 198 QLCNIC_PEG_HALT_STATUS2, 199 -1 200 }; 201 202 203 static const u32 ext_diag_registers[] = { 204 CRB_XG_STATE_P3P, 205 ISR_INT_STATE_REG, 206 QLCNIC_CRB_PEG_NET_0+0x3c, 207 QLCNIC_CRB_PEG_NET_1+0x3c, 208 QLCNIC_CRB_PEG_NET_2+0x3c, 209 QLCNIC_CRB_PEG_NET_4+0x3c, 210 -1 211 }; 212 213 #define QLCNIC_MGMT_API_VERSION 2 214 #define QLCNIC_ETHTOOL_REGS_VER 3 215 216 static int qlcnic_get_regs_len(struct net_device *dev) 217 { 218 struct qlcnic_adapter *adapter = netdev_priv(dev); 219 u32 len; 220 221 if (qlcnic_83xx_check(adapter)) 222 len = qlcnic_83xx_get_regs_len(adapter); 223 else 224 len = sizeof(ext_diag_registers) + sizeof(diag_registers); 225 226 return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1; 227 } 228 229 static int qlcnic_get_eeprom_len(struct net_device *dev) 230 { 231 return QLCNIC_FLASH_TOTAL_SIZE; 232 } 233 234 static void 235 qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) 236 { 237 struct qlcnic_adapter *adapter = netdev_priv(dev); 238 u32 fw_major, fw_minor, fw_build; 239 fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); 240 fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); 241 fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); 242 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 243 "%d.%d.%d", fw_major, fw_minor, fw_build); 244 245 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 246 sizeof(drvinfo->bus_info)); 247 strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver)); 248 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID, 249 sizeof(drvinfo->version)); 250 } 251 252 static int 253 qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 254 { 255 struct qlcnic_adapter *adapter = netdev_priv(dev); 256 257 if (qlcnic_82xx_check(adapter)) 258 return qlcnic_82xx_get_settings(adapter, ecmd); 259 else if (qlcnic_83xx_check(adapter)) 260 return qlcnic_83xx_get_settings(adapter, ecmd); 261 262 return -EIO; 263 } 264 265 int qlcnic_82xx_get_settings(struct qlcnic_adapter *adapter, 266 struct ethtool_cmd *ecmd) 267 { 268 struct qlcnic_hardware_context *ahw = adapter->ahw; 269 u32 speed, reg; 270 int check_sfp_module = 0, err = 0; 271 u16 pcifn = ahw->pci_func; 272 273 /* read which mode */ 274 if (adapter->ahw->port_type == QLCNIC_GBE) { 275 ecmd->supported = (SUPPORTED_10baseT_Half | 276 SUPPORTED_10baseT_Full | 277 SUPPORTED_100baseT_Half | 278 SUPPORTED_100baseT_Full | 279 SUPPORTED_1000baseT_Half | 280 SUPPORTED_1000baseT_Full); 281 282 ecmd->advertising = (ADVERTISED_100baseT_Half | 283 ADVERTISED_100baseT_Full | 284 ADVERTISED_1000baseT_Half | 285 ADVERTISED_1000baseT_Full); 286 287 ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); 288 ecmd->duplex = adapter->ahw->link_duplex; 289 ecmd->autoneg = adapter->ahw->link_autoneg; 290 291 } else if (adapter->ahw->port_type == QLCNIC_XGBE) { 292 u32 val = 0; 293 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err); 294 295 if (val == QLCNIC_PORT_MODE_802_3_AP) { 296 ecmd->supported = SUPPORTED_1000baseT_Full; 297 ecmd->advertising = ADVERTISED_1000baseT_Full; 298 } else { 299 ecmd->supported = SUPPORTED_10000baseT_Full; 300 ecmd->advertising = ADVERTISED_10000baseT_Full; 301 } 302 303 if (netif_running(adapter->netdev) && ahw->has_link_events) { 304 if (ahw->linkup) { 305 reg = QLCRD32(adapter, 306 P3P_LINK_SPEED_REG(pcifn), &err); 307 speed = P3P_LINK_SPEED_VAL(pcifn, reg); 308 ahw->link_speed = speed * P3P_LINK_SPEED_MHZ; 309 } 310 311 ethtool_cmd_speed_set(ecmd, ahw->link_speed); 312 ecmd->autoneg = ahw->link_autoneg; 313 ecmd->duplex = ahw->link_duplex; 314 goto skip; 315 } 316 317 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); 318 ecmd->duplex = DUPLEX_UNKNOWN; 319 ecmd->autoneg = AUTONEG_DISABLE; 320 } else 321 return -EIO; 322 323 skip: 324 ecmd->phy_address = adapter->ahw->physical_port; 325 ecmd->transceiver = XCVR_EXTERNAL; 326 327 switch (adapter->ahw->board_type) { 328 case QLCNIC_BRDTYPE_P3P_REF_QG: 329 case QLCNIC_BRDTYPE_P3P_4_GB: 330 case QLCNIC_BRDTYPE_P3P_4_GB_MM: 331 332 ecmd->supported |= SUPPORTED_Autoneg; 333 ecmd->advertising |= ADVERTISED_Autoneg; 334 case QLCNIC_BRDTYPE_P3P_10G_CX4: 335 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP: 336 case QLCNIC_BRDTYPE_P3P_10000_BASE_T: 337 ecmd->supported |= SUPPORTED_TP; 338 ecmd->advertising |= ADVERTISED_TP; 339 ecmd->port = PORT_TP; 340 ecmd->autoneg = adapter->ahw->link_autoneg; 341 break; 342 case QLCNIC_BRDTYPE_P3P_IMEZ: 343 case QLCNIC_BRDTYPE_P3P_XG_LOM: 344 case QLCNIC_BRDTYPE_P3P_HMEZ: 345 ecmd->supported |= SUPPORTED_MII; 346 ecmd->advertising |= ADVERTISED_MII; 347 ecmd->port = PORT_MII; 348 ecmd->autoneg = AUTONEG_DISABLE; 349 break; 350 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS: 351 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT: 352 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT: 353 ecmd->advertising |= ADVERTISED_TP; 354 ecmd->supported |= SUPPORTED_TP; 355 check_sfp_module = netif_running(adapter->netdev) && 356 ahw->has_link_events; 357 case QLCNIC_BRDTYPE_P3P_10G_XFP: 358 ecmd->supported |= SUPPORTED_FIBRE; 359 ecmd->advertising |= ADVERTISED_FIBRE; 360 ecmd->port = PORT_FIBRE; 361 ecmd->autoneg = AUTONEG_DISABLE; 362 break; 363 case QLCNIC_BRDTYPE_P3P_10G_TP: 364 if (adapter->ahw->port_type == QLCNIC_XGBE) { 365 ecmd->autoneg = AUTONEG_DISABLE; 366 ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); 367 ecmd->advertising |= 368 (ADVERTISED_FIBRE | ADVERTISED_TP); 369 ecmd->port = PORT_FIBRE; 370 check_sfp_module = netif_running(adapter->netdev) && 371 ahw->has_link_events; 372 } else { 373 ecmd->autoneg = AUTONEG_ENABLE; 374 ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); 375 ecmd->advertising |= 376 (ADVERTISED_TP | ADVERTISED_Autoneg); 377 ecmd->port = PORT_TP; 378 } 379 break; 380 default: 381 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", 382 adapter->ahw->board_type); 383 return -EIO; 384 } 385 386 if (check_sfp_module) { 387 switch (adapter->ahw->module_type) { 388 case LINKEVENT_MODULE_OPTICAL_UNKNOWN: 389 case LINKEVENT_MODULE_OPTICAL_SRLR: 390 case LINKEVENT_MODULE_OPTICAL_LRM: 391 case LINKEVENT_MODULE_OPTICAL_SFP_1G: 392 ecmd->port = PORT_FIBRE; 393 break; 394 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: 395 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: 396 case LINKEVENT_MODULE_TWINAX: 397 ecmd->port = PORT_TP; 398 break; 399 default: 400 ecmd->port = PORT_OTHER; 401 } 402 } 403 404 return 0; 405 } 406 407 static int qlcnic_set_port_config(struct qlcnic_adapter *adapter, 408 struct ethtool_cmd *ecmd) 409 { 410 u32 ret = 0, config = 0; 411 /* read which mode */ 412 if (ecmd->duplex) 413 config |= 0x1; 414 415 if (ecmd->autoneg) 416 config |= 0x2; 417 418 switch (ethtool_cmd_speed(ecmd)) { 419 case SPEED_10: 420 config |= (0 << 8); 421 break; 422 case SPEED_100: 423 config |= (1 << 8); 424 break; 425 case SPEED_1000: 426 config |= (10 << 8); 427 break; 428 default: 429 return -EIO; 430 } 431 432 ret = qlcnic_fw_cmd_set_port(adapter, config); 433 434 if (ret == QLCNIC_RCODE_NOT_SUPPORTED) 435 return -EOPNOTSUPP; 436 else if (ret) 437 return -EIO; 438 return ret; 439 } 440 441 static int qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 442 { 443 u32 ret = 0; 444 struct qlcnic_adapter *adapter = netdev_priv(dev); 445 446 if (adapter->ahw->port_type != QLCNIC_GBE) 447 return -EOPNOTSUPP; 448 449 if (qlcnic_83xx_check(adapter)) 450 ret = qlcnic_83xx_set_settings(adapter, ecmd); 451 else 452 ret = qlcnic_set_port_config(adapter, ecmd); 453 454 if (!ret) 455 return ret; 456 457 adapter->ahw->link_speed = ethtool_cmd_speed(ecmd); 458 adapter->ahw->link_duplex = ecmd->duplex; 459 adapter->ahw->link_autoneg = ecmd->autoneg; 460 461 if (!netif_running(dev)) 462 return 0; 463 464 dev->netdev_ops->ndo_stop(dev); 465 return dev->netdev_ops->ndo_open(dev); 466 } 467 468 static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter, 469 u32 *regs_buff) 470 { 471 int i, j = 0, err = 0; 472 473 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++) 474 regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]); 475 j = 0; 476 while (ext_diag_registers[j] != -1) 477 regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++], 478 &err); 479 return i; 480 } 481 482 static void 483 qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) 484 { 485 struct qlcnic_adapter *adapter = netdev_priv(dev); 486 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; 487 struct qlcnic_host_sds_ring *sds_ring; 488 u32 *regs_buff = p; 489 int ring, i = 0; 490 491 memset(p, 0, qlcnic_get_regs_len(dev)); 492 493 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) | 494 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device; 495 496 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff)); 497 regs_buff[1] = QLCNIC_MGMT_API_VERSION; 498 499 if (qlcnic_82xx_check(adapter)) 500 i = qlcnic_82xx_get_registers(adapter, regs_buff); 501 else 502 i = qlcnic_83xx_get_registers(adapter, regs_buff); 503 504 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) 505 return; 506 507 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/ 508 509 regs_buff[i++] = 1; /* No. of tx ring */ 510 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer)); 511 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer); 512 513 regs_buff[i++] = 2; /* No. of rx ring */ 514 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer); 515 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer); 516 517 regs_buff[i++] = adapter->max_sds_rings; 518 519 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 520 sds_ring = &(recv_ctx->sds_rings[ring]); 521 regs_buff[i++] = readl(sds_ring->crb_sts_consumer); 522 } 523 } 524 525 static u32 qlcnic_test_link(struct net_device *dev) 526 { 527 struct qlcnic_adapter *adapter = netdev_priv(dev); 528 int err = 0; 529 u32 val; 530 531 if (qlcnic_83xx_check(adapter)) { 532 val = qlcnic_83xx_test_link(adapter); 533 return (val & 1) ? 0 : 1; 534 } 535 val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err); 536 if (err == -EIO) 537 return err; 538 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val); 539 return (val == XG_LINK_UP_P3P) ? 0 : 1; 540 } 541 542 static int 543 qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 544 u8 *bytes) 545 { 546 struct qlcnic_adapter *adapter = netdev_priv(dev); 547 int offset; 548 int ret = -1; 549 550 if (qlcnic_83xx_check(adapter)) 551 return 0; 552 if (eeprom->len == 0) 553 return -EINVAL; 554 555 eeprom->magic = (adapter->pdev)->vendor | 556 ((adapter->pdev)->device << 16); 557 offset = eeprom->offset; 558 559 if (qlcnic_82xx_check(adapter)) 560 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes, 561 eeprom->len); 562 if (ret < 0) 563 return ret; 564 565 return 0; 566 } 567 568 static void 569 qlcnic_get_ringparam(struct net_device *dev, 570 struct ethtool_ringparam *ring) 571 { 572 struct qlcnic_adapter *adapter = netdev_priv(dev); 573 574 ring->rx_pending = adapter->num_rxd; 575 ring->rx_jumbo_pending = adapter->num_jumbo_rxd; 576 ring->tx_pending = adapter->num_txd; 577 578 ring->rx_max_pending = adapter->max_rxd; 579 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd; 580 ring->tx_max_pending = MAX_CMD_DESCRIPTORS; 581 } 582 583 static u32 584 qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name) 585 { 586 u32 num_desc; 587 num_desc = max(val, min); 588 num_desc = min(num_desc, max); 589 num_desc = roundup_pow_of_two(num_desc); 590 591 if (val != num_desc) { 592 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n", 593 qlcnic_driver_name, r_name, num_desc, val); 594 } 595 596 return num_desc; 597 } 598 599 static int 600 qlcnic_set_ringparam(struct net_device *dev, 601 struct ethtool_ringparam *ring) 602 { 603 struct qlcnic_adapter *adapter = netdev_priv(dev); 604 u16 num_rxd, num_jumbo_rxd, num_txd; 605 606 if (ring->rx_mini_pending) 607 return -EOPNOTSUPP; 608 609 num_rxd = qlcnic_validate_ringparam(ring->rx_pending, 610 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx"); 611 612 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending, 613 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd, 614 "rx jumbo"); 615 616 num_txd = qlcnic_validate_ringparam(ring->tx_pending, 617 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx"); 618 619 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd && 620 num_jumbo_rxd == adapter->num_jumbo_rxd) 621 return 0; 622 623 adapter->num_rxd = num_rxd; 624 adapter->num_jumbo_rxd = num_jumbo_rxd; 625 adapter->num_txd = num_txd; 626 627 return qlcnic_reset_context(adapter); 628 } 629 630 static void qlcnic_get_channels(struct net_device *dev, 631 struct ethtool_channels *channel) 632 { 633 int min; 634 struct qlcnic_adapter *adapter = netdev_priv(dev); 635 636 min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); 637 channel->max_rx = rounddown_pow_of_two(min); 638 channel->max_tx = adapter->ahw->max_tx_ques; 639 640 channel->rx_count = adapter->max_sds_rings; 641 channel->tx_count = adapter->ahw->max_tx_ques; 642 } 643 644 static int qlcnic_set_channels(struct net_device *dev, 645 struct ethtool_channels *channel) 646 { 647 struct qlcnic_adapter *adapter = netdev_priv(dev); 648 int err; 649 650 if (channel->other_count || channel->combined_count || 651 channel->tx_count != channel->max_tx) 652 return -EINVAL; 653 654 err = qlcnic_validate_max_rss(adapter, channel->rx_count); 655 if (err) 656 return err; 657 658 err = qlcnic_set_max_rss(adapter, channel->rx_count, 0); 659 netdev_info(dev, "allocated 0x%x sds rings\n", 660 adapter->max_sds_rings); 661 return err; 662 } 663 664 static void 665 qlcnic_get_pauseparam(struct net_device *netdev, 666 struct ethtool_pauseparam *pause) 667 { 668 struct qlcnic_adapter *adapter = netdev_priv(netdev); 669 int port = adapter->ahw->physical_port; 670 int err = 0; 671 __u32 val; 672 673 if (qlcnic_83xx_check(adapter)) { 674 qlcnic_83xx_get_pauseparam(adapter, pause); 675 return; 676 } 677 if (adapter->ahw->port_type == QLCNIC_GBE) { 678 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) 679 return; 680 /* get flow control settings */ 681 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err); 682 if (err == -EIO) 683 return; 684 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val); 685 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err); 686 if (err == -EIO) 687 return; 688 switch (port) { 689 case 0: 690 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val)); 691 break; 692 case 1: 693 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val)); 694 break; 695 case 2: 696 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val)); 697 break; 698 case 3: 699 default: 700 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val)); 701 break; 702 } 703 } else if (adapter->ahw->port_type == QLCNIC_XGBE) { 704 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS)) 705 return; 706 pause->rx_pause = 1; 707 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err); 708 if (err == -EIO) 709 return; 710 if (port == 0) 711 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val)); 712 else 713 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val)); 714 } else { 715 dev_err(&netdev->dev, "Unknown board type: %x\n", 716 adapter->ahw->port_type); 717 } 718 } 719 720 static int 721 qlcnic_set_pauseparam(struct net_device *netdev, 722 struct ethtool_pauseparam *pause) 723 { 724 struct qlcnic_adapter *adapter = netdev_priv(netdev); 725 int port = adapter->ahw->physical_port; 726 int err = 0; 727 __u32 val; 728 729 if (qlcnic_83xx_check(adapter)) 730 return qlcnic_83xx_set_pauseparam(adapter, pause); 731 732 /* read mode */ 733 if (adapter->ahw->port_type == QLCNIC_GBE) { 734 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) 735 return -EIO; 736 /* set flow control */ 737 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err); 738 if (err == -EIO) 739 return err; 740 741 if (pause->rx_pause) 742 qlcnic_gb_rx_flowctl(val); 743 else 744 qlcnic_gb_unset_rx_flowctl(val); 745 746 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), 747 val); 748 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val); 749 /* set autoneg */ 750 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err); 751 if (err == -EIO) 752 return err; 753 switch (port) { 754 case 0: 755 if (pause->tx_pause) 756 qlcnic_gb_unset_gb0_mask(val); 757 else 758 qlcnic_gb_set_gb0_mask(val); 759 break; 760 case 1: 761 if (pause->tx_pause) 762 qlcnic_gb_unset_gb1_mask(val); 763 else 764 qlcnic_gb_set_gb1_mask(val); 765 break; 766 case 2: 767 if (pause->tx_pause) 768 qlcnic_gb_unset_gb2_mask(val); 769 else 770 qlcnic_gb_set_gb2_mask(val); 771 break; 772 case 3: 773 default: 774 if (pause->tx_pause) 775 qlcnic_gb_unset_gb3_mask(val); 776 else 777 qlcnic_gb_set_gb3_mask(val); 778 break; 779 } 780 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val); 781 } else if (adapter->ahw->port_type == QLCNIC_XGBE) { 782 if (!pause->rx_pause || pause->autoneg) 783 return -EOPNOTSUPP; 784 785 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS)) 786 return -EIO; 787 788 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err); 789 if (err == -EIO) 790 return err; 791 if (port == 0) { 792 if (pause->tx_pause) 793 qlcnic_xg_unset_xg0_mask(val); 794 else 795 qlcnic_xg_set_xg0_mask(val); 796 } else { 797 if (pause->tx_pause) 798 qlcnic_xg_unset_xg1_mask(val); 799 else 800 qlcnic_xg_set_xg1_mask(val); 801 } 802 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val); 803 } else { 804 dev_err(&netdev->dev, "Unknown board type: %x\n", 805 adapter->ahw->port_type); 806 } 807 return 0; 808 } 809 810 static int qlcnic_reg_test(struct net_device *dev) 811 { 812 struct qlcnic_adapter *adapter = netdev_priv(dev); 813 u32 data_read; 814 int err = 0; 815 816 if (qlcnic_83xx_check(adapter)) 817 return qlcnic_83xx_reg_test(adapter); 818 819 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err); 820 if (err == -EIO) 821 return err; 822 if ((data_read & 0xffff) != adapter->pdev->vendor) 823 return 1; 824 825 return 0; 826 } 827 828 static int qlcnic_eeprom_test(struct net_device *dev) 829 { 830 struct qlcnic_adapter *adapter = netdev_priv(dev); 831 832 if (qlcnic_82xx_check(adapter)) 833 return 0; 834 835 return qlcnic_83xx_flash_test(adapter); 836 } 837 838 static int qlcnic_get_sset_count(struct net_device *dev, int sset) 839 { 840 int len; 841 842 struct qlcnic_adapter *adapter = netdev_priv(dev); 843 switch (sset) { 844 case ETH_SS_TEST: 845 return QLCNIC_TEST_LEN; 846 case ETH_SS_STATS: 847 len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN; 848 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) || 849 qlcnic_83xx_check(adapter)) 850 return len; 851 return qlcnic_82xx_statistics(); 852 default: 853 return -EOPNOTSUPP; 854 } 855 } 856 857 static int qlcnic_irq_test(struct net_device *netdev) 858 { 859 struct qlcnic_adapter *adapter = netdev_priv(netdev); 860 struct qlcnic_hardware_context *ahw = adapter->ahw; 861 struct qlcnic_cmd_args cmd; 862 int ret, max_sds_rings = adapter->max_sds_rings; 863 864 if (qlcnic_83xx_check(adapter)) 865 return qlcnic_83xx_interrupt_test(netdev); 866 867 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) 868 return -EIO; 869 870 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); 871 if (ret) 872 goto clear_diag_irq; 873 874 ahw->diag_cnt = 0; 875 ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); 876 if (ret) 877 goto free_diag_res; 878 879 cmd.req.arg[1] = ahw->pci_func; 880 ret = qlcnic_issue_cmd(adapter, &cmd); 881 if (ret) 882 goto done; 883 884 usleep_range(1000, 12000); 885 ret = !ahw->diag_cnt; 886 887 done: 888 qlcnic_free_mbx_args(&cmd); 889 890 free_diag_res: 891 qlcnic_diag_free_res(netdev, max_sds_rings); 892 893 clear_diag_irq: 894 adapter->max_sds_rings = max_sds_rings; 895 clear_bit(__QLCNIC_RESETTING, &adapter->state); 896 return ret; 897 } 898 899 #define QLCNIC_ILB_PKT_SIZE 64 900 #define QLCNIC_NUM_ILB_PKT 16 901 #define QLCNIC_ILB_MAX_RCV_LOOP 10 902 #define QLCNIC_LB_PKT_POLL_DELAY_MSEC 1 903 #define QLCNIC_LB_PKT_POLL_COUNT 20 904 905 static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[]) 906 { 907 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00}; 908 909 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE); 910 911 memcpy(data, mac, ETH_ALEN); 912 memcpy(data + ETH_ALEN, mac, ETH_ALEN); 913 914 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data)); 915 } 916 917 int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]) 918 { 919 unsigned char buff[QLCNIC_ILB_PKT_SIZE]; 920 qlcnic_create_loopback_buff(buff, mac); 921 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE); 922 } 923 924 int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) 925 { 926 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; 927 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; 928 struct sk_buff *skb; 929 int i, loop, cnt = 0; 930 931 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) { 932 skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); 933 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); 934 skb_put(skb, QLCNIC_ILB_PKT_SIZE); 935 adapter->ahw->diag_cnt = 0; 936 qlcnic_xmit_frame(skb, adapter->netdev); 937 loop = 0; 938 939 do { 940 msleep(QLCNIC_LB_PKT_POLL_DELAY_MSEC); 941 qlcnic_process_rcv_ring_diag(sds_ring); 942 if (loop++ > QLCNIC_LB_PKT_POLL_COUNT) 943 break; 944 } while (!adapter->ahw->diag_cnt); 945 946 dev_kfree_skb_any(skb); 947 948 if (!adapter->ahw->diag_cnt) 949 dev_warn(&adapter->pdev->dev, 950 "LB Test: packet #%d was not received\n", 951 i + 1); 952 else 953 cnt++; 954 } 955 if (cnt != i) { 956 dev_err(&adapter->pdev->dev, 957 "LB Test: failed, TX[%d], RX[%d]\n", i, cnt); 958 if (mode != QLCNIC_ILB_MODE) 959 dev_warn(&adapter->pdev->dev, 960 "WARNING: Please check loopback cable\n"); 961 return -1; 962 } 963 return 0; 964 } 965 966 int qlcnic_loopback_test(struct net_device *netdev, u8 mode) 967 { 968 struct qlcnic_adapter *adapter = netdev_priv(netdev); 969 int max_sds_rings = adapter->max_sds_rings; 970 struct qlcnic_host_sds_ring *sds_ring; 971 struct qlcnic_hardware_context *ahw = adapter->ahw; 972 int loop = 0; 973 int ret; 974 975 if (qlcnic_83xx_check(adapter)) 976 return qlcnic_83xx_loopback_test(netdev, mode); 977 978 if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { 979 dev_info(&adapter->pdev->dev, 980 "Firmware do not support loopback test\n"); 981 return -EOPNOTSUPP; 982 } 983 984 dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n", 985 mode == QLCNIC_ILB_MODE ? "internal" : "external"); 986 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { 987 dev_warn(&adapter->pdev->dev, 988 "Loopback test not supported in nonprivileged mode\n"); 989 return 0; 990 } 991 992 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) 993 return -EBUSY; 994 995 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST); 996 if (ret) 997 goto clear_it; 998 999 sds_ring = &adapter->recv_ctx->sds_rings[0]; 1000 ret = qlcnic_set_lb_mode(adapter, mode); 1001 if (ret) 1002 goto free_res; 1003 1004 ahw->diag_cnt = 0; 1005 do { 1006 msleep(500); 1007 qlcnic_process_rcv_ring_diag(sds_ring); 1008 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { 1009 netdev_info(netdev, "firmware didnt respond to loopback" 1010 " configure request\n"); 1011 ret = -QLCNIC_FW_NOT_RESPOND; 1012 goto free_res; 1013 } else if (adapter->ahw->diag_cnt) { 1014 ret = adapter->ahw->diag_cnt; 1015 goto free_res; 1016 } 1017 } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state)); 1018 1019 ret = qlcnic_do_lb_test(adapter, mode); 1020 1021 qlcnic_clear_lb_mode(adapter, mode); 1022 1023 free_res: 1024 qlcnic_diag_free_res(netdev, max_sds_rings); 1025 1026 clear_it: 1027 adapter->max_sds_rings = max_sds_rings; 1028 clear_bit(__QLCNIC_RESETTING, &adapter->state); 1029 return ret; 1030 } 1031 1032 static void 1033 qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, 1034 u64 *data) 1035 { 1036 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN); 1037 1038 data[0] = qlcnic_reg_test(dev); 1039 if (data[0]) 1040 eth_test->flags |= ETH_TEST_FL_FAILED; 1041 1042 data[1] = (u64) qlcnic_test_link(dev); 1043 if (data[1]) 1044 eth_test->flags |= ETH_TEST_FL_FAILED; 1045 1046 if (eth_test->flags & ETH_TEST_FL_OFFLINE) { 1047 data[2] = qlcnic_irq_test(dev); 1048 if (data[2]) 1049 eth_test->flags |= ETH_TEST_FL_FAILED; 1050 1051 data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE); 1052 if (data[3]) 1053 eth_test->flags |= ETH_TEST_FL_FAILED; 1054 1055 if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) { 1056 data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE); 1057 if (data[4]) 1058 eth_test->flags |= ETH_TEST_FL_FAILED; 1059 eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; 1060 } 1061 1062 data[5] = qlcnic_eeprom_test(dev); 1063 if (data[5]) 1064 eth_test->flags |= ETH_TEST_FL_FAILED; 1065 } 1066 } 1067 1068 static void 1069 qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) 1070 { 1071 struct qlcnic_adapter *adapter = netdev_priv(dev); 1072 int index, i, num_stats; 1073 1074 switch (stringset) { 1075 case ETH_SS_TEST: 1076 memcpy(data, *qlcnic_gstrings_test, 1077 QLCNIC_TEST_LEN * ETH_GSTRING_LEN); 1078 break; 1079 case ETH_SS_STATS: 1080 for (index = 0; index < QLCNIC_STATS_LEN; index++) { 1081 memcpy(data + index * ETH_GSTRING_LEN, 1082 qlcnic_gstrings_stats[index].stat_string, 1083 ETH_GSTRING_LEN); 1084 } 1085 if (qlcnic_83xx_check(adapter)) { 1086 num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings); 1087 for (i = 0; i < num_stats; i++, index++) 1088 memcpy(data + index * ETH_GSTRING_LEN, 1089 qlcnic_83xx_tx_stats_strings[i], 1090 ETH_GSTRING_LEN); 1091 num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); 1092 for (i = 0; i < num_stats; i++, index++) 1093 memcpy(data + index * ETH_GSTRING_LEN, 1094 qlcnic_83xx_mac_stats_strings[i], 1095 ETH_GSTRING_LEN); 1096 num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings); 1097 for (i = 0; i < num_stats; i++, index++) 1098 memcpy(data + index * ETH_GSTRING_LEN, 1099 qlcnic_83xx_rx_stats_strings[i], 1100 ETH_GSTRING_LEN); 1101 return; 1102 } else { 1103 num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); 1104 for (i = 0; i < num_stats; i++, index++) 1105 memcpy(data + index * ETH_GSTRING_LEN, 1106 qlcnic_83xx_mac_stats_strings[i], 1107 ETH_GSTRING_LEN); 1108 } 1109 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) 1110 return; 1111 num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats); 1112 for (i = 0; i < num_stats; index++, i++) { 1113 memcpy(data + index * ETH_GSTRING_LEN, 1114 qlcnic_device_gstrings_stats[i], 1115 ETH_GSTRING_LEN); 1116 } 1117 } 1118 } 1119 1120 static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type) 1121 { 1122 if (type == QLCNIC_MAC_STATS) { 1123 struct qlcnic_mac_statistics *mac_stats = 1124 (struct qlcnic_mac_statistics *)stats; 1125 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames); 1126 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes); 1127 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts); 1128 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts); 1129 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt); 1130 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt); 1131 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts); 1132 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts); 1133 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts); 1134 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts); 1135 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts); 1136 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts); 1137 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts); 1138 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames); 1139 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes); 1140 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts); 1141 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts); 1142 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt); 1143 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt); 1144 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts); 1145 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts); 1146 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts); 1147 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts); 1148 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts); 1149 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts); 1150 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts); 1151 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error); 1152 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small); 1153 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large); 1154 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber); 1155 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped); 1156 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error); 1157 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error); 1158 } else if (type == QLCNIC_ESW_STATS) { 1159 struct __qlcnic_esw_statistics *esw_stats = 1160 (struct __qlcnic_esw_statistics *)stats; 1161 *data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames); 1162 *data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames); 1163 *data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames); 1164 *data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames); 1165 *data++ = QLCNIC_FILL_STATS(esw_stats->errors); 1166 *data++ = QLCNIC_FILL_STATS(esw_stats->local_frames); 1167 *data++ = QLCNIC_FILL_STATS(esw_stats->numbytes); 1168 } 1169 return data; 1170 } 1171 1172 static void qlcnic_get_ethtool_stats(struct net_device *dev, 1173 struct ethtool_stats *stats, u64 *data) 1174 { 1175 struct qlcnic_adapter *adapter = netdev_priv(dev); 1176 struct qlcnic_esw_statistics port_stats; 1177 struct qlcnic_mac_statistics mac_stats; 1178 int index, ret, length, size; 1179 char *p; 1180 1181 memset(data, 0, stats->n_stats * sizeof(u64)); 1182 length = QLCNIC_STATS_LEN; 1183 for (index = 0; index < length; index++) { 1184 p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset; 1185 size = qlcnic_gstrings_stats[index].sizeof_stat; 1186 *data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p)); 1187 } 1188 1189 if (qlcnic_83xx_check(adapter)) { 1190 if (adapter->ahw->linkup) 1191 qlcnic_83xx_get_stats(adapter, data); 1192 return; 1193 } else { 1194 /* Retrieve MAC statistics from firmware */ 1195 memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics)); 1196 qlcnic_get_mac_stats(adapter, &mac_stats); 1197 data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS); 1198 } 1199 1200 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) 1201 return; 1202 1203 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics)); 1204 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, 1205 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx); 1206 if (ret) 1207 return; 1208 1209 data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS); 1210 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, 1211 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); 1212 if (ret) 1213 return; 1214 1215 qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS); 1216 } 1217 1218 static int qlcnic_set_led(struct net_device *dev, 1219 enum ethtool_phys_id_state state) 1220 { 1221 struct qlcnic_adapter *adapter = netdev_priv(dev); 1222 int max_sds_rings = adapter->max_sds_rings; 1223 int err = -EIO, active = 1; 1224 1225 if (qlcnic_83xx_check(adapter)) 1226 return qlcnic_83xx_set_led(dev, state); 1227 1228 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { 1229 netdev_warn(dev, "LED test not supported for non " 1230 "privilege function\n"); 1231 return -EOPNOTSUPP; 1232 } 1233 1234 switch (state) { 1235 case ETHTOOL_ID_ACTIVE: 1236 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) 1237 return -EBUSY; 1238 1239 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) 1240 break; 1241 1242 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { 1243 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) 1244 break; 1245 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); 1246 } 1247 1248 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) { 1249 err = 0; 1250 break; 1251 } 1252 1253 dev_err(&adapter->pdev->dev, 1254 "Failed to set LED blink state.\n"); 1255 break; 1256 1257 case ETHTOOL_ID_INACTIVE: 1258 active = 0; 1259 1260 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) 1261 break; 1262 1263 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { 1264 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) 1265 break; 1266 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); 1267 } 1268 1269 if (adapter->nic_ops->config_led(adapter, 0, 0xf)) 1270 dev_err(&adapter->pdev->dev, 1271 "Failed to reset LED blink state.\n"); 1272 1273 break; 1274 1275 default: 1276 return -EINVAL; 1277 } 1278 1279 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) 1280 qlcnic_diag_free_res(dev, max_sds_rings); 1281 1282 if (!active || err) 1283 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); 1284 1285 return err; 1286 } 1287 1288 static void 1289 qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 1290 { 1291 struct qlcnic_adapter *adapter = netdev_priv(dev); 1292 u32 wol_cfg; 1293 int err = 0; 1294 1295 if (qlcnic_83xx_check(adapter)) 1296 return; 1297 wol->supported = 0; 1298 wol->wolopts = 0; 1299 1300 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err); 1301 if (err == -EIO) 1302 return; 1303 if (wol_cfg & (1UL << adapter->portnum)) 1304 wol->supported |= WAKE_MAGIC; 1305 1306 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err); 1307 if (wol_cfg & (1UL << adapter->portnum)) 1308 wol->wolopts |= WAKE_MAGIC; 1309 } 1310 1311 static int 1312 qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 1313 { 1314 struct qlcnic_adapter *adapter = netdev_priv(dev); 1315 u32 wol_cfg; 1316 int err = 0; 1317 1318 if (qlcnic_83xx_check(adapter)) 1319 return -EOPNOTSUPP; 1320 if (wol->wolopts & ~WAKE_MAGIC) 1321 return -EINVAL; 1322 1323 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err); 1324 if (err == -EIO) 1325 return err; 1326 if (!(wol_cfg & (1 << adapter->portnum))) 1327 return -EOPNOTSUPP; 1328 1329 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err); 1330 if (err == -EIO) 1331 return err; 1332 if (wol->wolopts & WAKE_MAGIC) 1333 wol_cfg |= 1UL << adapter->portnum; 1334 else 1335 wol_cfg &= ~(1UL << adapter->portnum); 1336 1337 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg); 1338 1339 return 0; 1340 } 1341 1342 /* 1343 * Set the coalescing parameters. Currently only normal is supported. 1344 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the 1345 * firmware coalescing to default. 1346 */ 1347 static int qlcnic_set_intr_coalesce(struct net_device *netdev, 1348 struct ethtool_coalesce *ethcoal) 1349 { 1350 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1351 struct qlcnic_nic_intr_coalesce *coal; 1352 u32 rx_coalesce_usecs, rx_max_frames; 1353 u32 tx_coalesce_usecs, tx_max_frames; 1354 1355 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) 1356 return -EINVAL; 1357 1358 /* 1359 * Return Error if unsupported values or 1360 * unsupported parameters are set. 1361 */ 1362 if (ethcoal->rx_coalesce_usecs > 0xffff || 1363 ethcoal->rx_max_coalesced_frames > 0xffff || 1364 ethcoal->tx_coalesce_usecs > 0xffff || 1365 ethcoal->tx_max_coalesced_frames > 0xffff || 1366 ethcoal->rx_coalesce_usecs_irq || 1367 ethcoal->rx_max_coalesced_frames_irq || 1368 ethcoal->tx_coalesce_usecs_irq || 1369 ethcoal->tx_max_coalesced_frames_irq || 1370 ethcoal->stats_block_coalesce_usecs || 1371 ethcoal->use_adaptive_rx_coalesce || 1372 ethcoal->use_adaptive_tx_coalesce || 1373 ethcoal->pkt_rate_low || 1374 ethcoal->rx_coalesce_usecs_low || 1375 ethcoal->rx_max_coalesced_frames_low || 1376 ethcoal->tx_coalesce_usecs_low || 1377 ethcoal->tx_max_coalesced_frames_low || 1378 ethcoal->pkt_rate_high || 1379 ethcoal->rx_coalesce_usecs_high || 1380 ethcoal->rx_max_coalesced_frames_high || 1381 ethcoal->tx_coalesce_usecs_high || 1382 ethcoal->tx_max_coalesced_frames_high) 1383 return -EINVAL; 1384 1385 coal = &adapter->ahw->coal; 1386 1387 if (qlcnic_83xx_check(adapter)) { 1388 if (!ethcoal->tx_coalesce_usecs || 1389 !ethcoal->tx_max_coalesced_frames || 1390 !ethcoal->rx_coalesce_usecs || 1391 !ethcoal->rx_max_coalesced_frames) { 1392 coal->flag = QLCNIC_INTR_DEFAULT; 1393 coal->type = QLCNIC_INTR_COAL_TYPE_RX; 1394 coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US; 1395 coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS; 1396 coal->tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US; 1397 coal->tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS; 1398 } else { 1399 tx_coalesce_usecs = ethcoal->tx_coalesce_usecs; 1400 tx_max_frames = ethcoal->tx_max_coalesced_frames; 1401 rx_coalesce_usecs = ethcoal->rx_coalesce_usecs; 1402 rx_max_frames = ethcoal->rx_max_coalesced_frames; 1403 coal->flag = 0; 1404 1405 if ((coal->rx_time_us == rx_coalesce_usecs) && 1406 (coal->rx_packets == rx_max_frames)) { 1407 coal->type = QLCNIC_INTR_COAL_TYPE_TX; 1408 coal->tx_time_us = tx_coalesce_usecs; 1409 coal->tx_packets = tx_max_frames; 1410 } else if ((coal->tx_time_us == tx_coalesce_usecs) && 1411 (coal->tx_packets == tx_max_frames)) { 1412 coal->type = QLCNIC_INTR_COAL_TYPE_RX; 1413 coal->rx_time_us = rx_coalesce_usecs; 1414 coal->rx_packets = rx_max_frames; 1415 } else { 1416 coal->type = QLCNIC_INTR_COAL_TYPE_RX; 1417 coal->rx_time_us = rx_coalesce_usecs; 1418 coal->rx_packets = rx_max_frames; 1419 coal->tx_time_us = tx_coalesce_usecs; 1420 coal->tx_packets = tx_max_frames; 1421 } 1422 } 1423 } else { 1424 if (!ethcoal->rx_coalesce_usecs || 1425 !ethcoal->rx_max_coalesced_frames) { 1426 coal->flag = QLCNIC_INTR_DEFAULT; 1427 coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US; 1428 coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS; 1429 } else { 1430 coal->flag = 0; 1431 coal->rx_time_us = ethcoal->rx_coalesce_usecs; 1432 coal->rx_packets = ethcoal->rx_max_coalesced_frames; 1433 } 1434 } 1435 1436 qlcnic_config_intr_coalesce(adapter); 1437 1438 return 0; 1439 } 1440 1441 static int qlcnic_get_intr_coalesce(struct net_device *netdev, 1442 struct ethtool_coalesce *ethcoal) 1443 { 1444 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1445 1446 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) 1447 return -EINVAL; 1448 1449 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us; 1450 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets; 1451 ethcoal->tx_coalesce_usecs = adapter->ahw->coal.tx_time_us; 1452 ethcoal->tx_max_coalesced_frames = adapter->ahw->coal.tx_packets; 1453 1454 return 0; 1455 } 1456 1457 static u32 qlcnic_get_msglevel(struct net_device *netdev) 1458 { 1459 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1460 1461 return adapter->ahw->msg_enable; 1462 } 1463 1464 static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) 1465 { 1466 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1467 1468 adapter->ahw->msg_enable = msglvl; 1469 } 1470 1471 static int 1472 qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) 1473 { 1474 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1475 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 1476 1477 if (!fw_dump->tmpl_hdr) { 1478 netdev_err(adapter->netdev, "FW Dump not supported\n"); 1479 return -ENOTSUPP; 1480 } 1481 1482 if (fw_dump->clr) 1483 dump->len = fw_dump->tmpl_hdr->size + fw_dump->size; 1484 else 1485 dump->len = 0; 1486 1487 if (!fw_dump->enable) 1488 dump->flag = ETH_FW_DUMP_DISABLE; 1489 else 1490 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 1491 1492 dump->version = adapter->fw_version; 1493 return 0; 1494 } 1495 1496 static int 1497 qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, 1498 void *buffer) 1499 { 1500 int i, copy_sz; 1501 u32 *hdr_ptr; 1502 __le32 *data; 1503 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1504 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 1505 1506 if (!fw_dump->tmpl_hdr) { 1507 netdev_err(netdev, "FW Dump not supported\n"); 1508 return -ENOTSUPP; 1509 } 1510 1511 if (!fw_dump->clr) { 1512 netdev_info(netdev, "Dump not available\n"); 1513 return -EINVAL; 1514 } 1515 /* Copy template header first */ 1516 copy_sz = fw_dump->tmpl_hdr->size; 1517 hdr_ptr = (u32 *) fw_dump->tmpl_hdr; 1518 data = buffer; 1519 for (i = 0; i < copy_sz/sizeof(u32); i++) 1520 *data++ = cpu_to_le32(*hdr_ptr++); 1521 1522 /* Copy captured dump data */ 1523 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); 1524 dump->len = copy_sz + fw_dump->size; 1525 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 1526 1527 /* Free dump area once data has been captured */ 1528 vfree(fw_dump->data); 1529 fw_dump->data = NULL; 1530 fw_dump->clr = 0; 1531 netdev_info(netdev, "extracted the FW dump Successfully\n"); 1532 return 0; 1533 } 1534 1535 static int 1536 qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) 1537 { 1538 int i; 1539 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1540 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 1541 u32 state; 1542 1543 switch (val->flag) { 1544 case QLCNIC_FORCE_FW_DUMP_KEY: 1545 if (!fw_dump->tmpl_hdr) { 1546 netdev_err(netdev, "FW dump not supported\n"); 1547 return -ENOTSUPP; 1548 } 1549 if (!fw_dump->enable) { 1550 netdev_info(netdev, "FW dump not enabled\n"); 1551 return 0; 1552 } 1553 if (fw_dump->clr) { 1554 netdev_info(netdev, 1555 "Previous dump not cleared, not forcing dump\n"); 1556 return 0; 1557 } 1558 netdev_info(netdev, "Forcing a FW dump\n"); 1559 qlcnic_dev_request_reset(adapter, val->flag); 1560 break; 1561 case QLCNIC_DISABLE_FW_DUMP: 1562 if (fw_dump->enable && fw_dump->tmpl_hdr) { 1563 netdev_info(netdev, "Disabling FW dump\n"); 1564 fw_dump->enable = 0; 1565 } 1566 return 0; 1567 case QLCNIC_ENABLE_FW_DUMP: 1568 if (!fw_dump->tmpl_hdr) { 1569 netdev_err(netdev, "FW dump not supported\n"); 1570 return -ENOTSUPP; 1571 } 1572 if (!fw_dump->enable) { 1573 netdev_info(netdev, "Enabling FW dump\n"); 1574 fw_dump->enable = 1; 1575 } 1576 return 0; 1577 case QLCNIC_FORCE_FW_RESET: 1578 netdev_info(netdev, "Forcing a FW reset\n"); 1579 qlcnic_dev_request_reset(adapter, val->flag); 1580 adapter->flags &= ~QLCNIC_FW_RESET_OWNER; 1581 return 0; 1582 case QLCNIC_SET_QUIESCENT: 1583 case QLCNIC_RESET_QUIESCENT: 1584 state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); 1585 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) 1586 netdev_info(netdev, "Device in FAILED state\n"); 1587 return 0; 1588 default: 1589 if (!fw_dump->tmpl_hdr) { 1590 netdev_err(netdev, "FW dump not supported\n"); 1591 return -ENOTSUPP; 1592 } 1593 for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { 1594 if (val->flag == qlcnic_fw_dump_level[i]) { 1595 fw_dump->tmpl_hdr->drv_cap_mask = 1596 val->flag; 1597 netdev_info(netdev, "Driver mask changed to: 0x%x\n", 1598 fw_dump->tmpl_hdr->drv_cap_mask); 1599 return 0; 1600 } 1601 } 1602 netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); 1603 return -EINVAL; 1604 } 1605 return 0; 1606 } 1607 1608 const struct ethtool_ops qlcnic_ethtool_ops = { 1609 .get_settings = qlcnic_get_settings, 1610 .set_settings = qlcnic_set_settings, 1611 .get_drvinfo = qlcnic_get_drvinfo, 1612 .get_regs_len = qlcnic_get_regs_len, 1613 .get_regs = qlcnic_get_regs, 1614 .get_link = ethtool_op_get_link, 1615 .get_eeprom_len = qlcnic_get_eeprom_len, 1616 .get_eeprom = qlcnic_get_eeprom, 1617 .get_ringparam = qlcnic_get_ringparam, 1618 .set_ringparam = qlcnic_set_ringparam, 1619 .get_channels = qlcnic_get_channels, 1620 .set_channels = qlcnic_set_channels, 1621 .get_pauseparam = qlcnic_get_pauseparam, 1622 .set_pauseparam = qlcnic_set_pauseparam, 1623 .get_wol = qlcnic_get_wol, 1624 .set_wol = qlcnic_set_wol, 1625 .self_test = qlcnic_diag_test, 1626 .get_strings = qlcnic_get_strings, 1627 .get_ethtool_stats = qlcnic_get_ethtool_stats, 1628 .get_sset_count = qlcnic_get_sset_count, 1629 .get_coalesce = qlcnic_get_intr_coalesce, 1630 .set_coalesce = qlcnic_set_intr_coalesce, 1631 .set_phys_id = qlcnic_set_led, 1632 .set_msglevel = qlcnic_set_msglevel, 1633 .get_msglevel = qlcnic_get_msglevel, 1634 .get_dump_flag = qlcnic_get_dump_flag, 1635 .get_dump_data = qlcnic_get_dump_data, 1636 .set_dump = qlcnic_set_dump, 1637 }; 1638 1639 const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = { 1640 .get_settings = qlcnic_get_settings, 1641 .get_drvinfo = qlcnic_get_drvinfo, 1642 .get_regs_len = qlcnic_get_regs_len, 1643 .get_regs = qlcnic_get_regs, 1644 .get_link = ethtool_op_get_link, 1645 .get_eeprom_len = qlcnic_get_eeprom_len, 1646 .get_eeprom = qlcnic_get_eeprom, 1647 .get_ringparam = qlcnic_get_ringparam, 1648 .set_ringparam = qlcnic_set_ringparam, 1649 .get_channels = qlcnic_get_channels, 1650 .get_pauseparam = qlcnic_get_pauseparam, 1651 .get_wol = qlcnic_get_wol, 1652 .get_strings = qlcnic_get_strings, 1653 .get_ethtool_stats = qlcnic_get_ethtool_stats, 1654 .get_sset_count = qlcnic_get_sset_count, 1655 .get_coalesce = qlcnic_get_intr_coalesce, 1656 .set_coalesce = qlcnic_set_intr_coalesce, 1657 .set_msglevel = qlcnic_set_msglevel, 1658 .get_msglevel = qlcnic_get_msglevel, 1659 }; 1660