2601 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic qlcnic NIC Driver4 * Copyright (c) 2009-2013 QLogic Corporation5 */6 7#include "qlcnic_sriov.h"8#include "qlcnic.h"9#include "qlcnic_hw.h"10 11/* Reset template definitions */12#define QLC_83XX_RESTART_TEMPLATE_SIZE 0x200013#define QLC_83XX_RESET_TEMPLATE_ADDR 0x4F000014#define QLC_83XX_RESET_SEQ_VERSION 0x010115 16#define QLC_83XX_OPCODE_NOP 0x000017#define QLC_83XX_OPCODE_WRITE_LIST 0x000118#define QLC_83XX_OPCODE_READ_WRITE_LIST 0x000219#define QLC_83XX_OPCODE_POLL_LIST 0x000420#define QLC_83XX_OPCODE_POLL_WRITE_LIST 0x000821#define QLC_83XX_OPCODE_READ_MODIFY_WRITE 0x001022#define QLC_83XX_OPCODE_SEQ_PAUSE 0x002023#define QLC_83XX_OPCODE_SEQ_END 0x004024#define QLC_83XX_OPCODE_TMPL_END 0x008025#define QLC_83XX_OPCODE_POLL_READ_LIST 0x010026 27/* EPORT control registers */28#define QLC_83XX_RESET_CONTROL 0x28084E5029#define QLC_83XX_RESET_REG 0x28084E6030#define QLC_83XX_RESET_PORT0 0x28084E7031#define QLC_83XX_RESET_PORT1 0x28084E8032#define QLC_83XX_RESET_PORT2 0x28084E9033#define QLC_83XX_RESET_PORT3 0x28084EA034#define QLC_83XX_RESET_SRESHIM 0x28084EB035#define QLC_83XX_RESET_EPGSHIM 0x28084EC036#define QLC_83XX_RESET_ETHERPCS 0x28084ED037 38static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter);39static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev);40static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);41static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);42static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *);43static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);44 45/* Template header */46struct qlc_83xx_reset_hdr {47#if defined(__LITTLE_ENDIAN)48 u16 version;49 u16 signature;50 u16 size;51 u16 entries;52 u16 hdr_size;53 u16 checksum;54 u16 init_offset;55 u16 start_offset;56#elif defined(__BIG_ENDIAN)57 u16 signature;58 u16 version;59 u16 entries;60 u16 size;61 u16 checksum;62 u16 hdr_size;63 u16 start_offset;64 u16 init_offset;65#endif66} __packed;67 68/* Command entry header. */69struct qlc_83xx_entry_hdr {70#if defined(__LITTLE_ENDIAN)71 u16 cmd;72 u16 size;73 u16 count;74 u16 delay;75#elif defined(__BIG_ENDIAN)76 u16 size;77 u16 cmd;78 u16 delay;79 u16 count;80#endif81} __packed;82 83/* Generic poll command */84struct qlc_83xx_poll {85 u32 mask;86 u32 status;87} __packed;88 89/* Read modify write command */90struct qlc_83xx_rmw {91 u32 mask;92 u32 xor_value;93 u32 or_value;94#if defined(__LITTLE_ENDIAN)95 u8 shl;96 u8 shr;97 u8 index_a;98 u8 rsvd;99#elif defined(__BIG_ENDIAN)100 u8 rsvd;101 u8 index_a;102 u8 shr;103 u8 shl;104#endif105} __packed;106 107/* Generic command with 2 DWORD */108struct qlc_83xx_entry {109 u32 arg1;110 u32 arg2;111} __packed;112 113/* Generic command with 4 DWORD */114struct qlc_83xx_quad_entry {115 u32 dr_addr;116 u32 dr_value;117 u32 ar_addr;118 u32 ar_value;119} __packed;120static const char *const qlc_83xx_idc_states[] = {121 "Unknown",122 "Cold",123 "Init",124 "Ready",125 "Need Reset",126 "Need Quiesce",127 "Failed",128 "Quiesce"129};130 131static int132qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter)133{134 u32 val;135 136 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);137 if ((val & 0xFFFF))138 return 1;139 else140 return 0;141}142 143static void qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter *adapter)144{145 u32 cur, prev;146 cur = adapter->ahw->idc.curr_state;147 prev = adapter->ahw->idc.prev_state;148 149 dev_info(&adapter->pdev->dev,150 "current state = %s, prev state = %s\n",151 adapter->ahw->idc.name[cur],152 adapter->ahw->idc.name[prev]);153}154 155static int qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter,156 u8 mode, int lock)157{158 u32 val;159 int seconds;160 161 if (lock) {162 if (qlcnic_83xx_lock_driver(adapter))163 return -EBUSY;164 }165 166 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);167 val |= (adapter->portnum & 0xf);168 val |= mode << 7;169 if (mode)170 seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;171 else172 seconds = jiffies / HZ;173 174 val |= seconds << 8;175 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT, val);176 adapter->ahw->idc.sec_counter = jiffies / HZ;177 178 if (lock)179 qlcnic_83xx_unlock_driver(adapter);180 181 return 0;182}183 184static void qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter *adapter)185{186 u32 val;187 188 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION);189 val = val & ~(0x3 << (adapter->portnum * 2));190 val = val | (QLC_83XX_IDC_MINOR_VERSION << (adapter->portnum * 2));191 QLCWRX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION, val);192}193 194static int qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter *adapter,195 int lock)196{197 u32 val;198 199 if (lock) {200 if (qlcnic_83xx_lock_driver(adapter))201 return -EBUSY;202 }203 204 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);205 val = val & ~0xFF;206 val = val | QLC_83XX_IDC_MAJOR_VERSION;207 QLCWRX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION, val);208 209 if (lock)210 qlcnic_83xx_unlock_driver(adapter);211 212 return 0;213}214 215static int216qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter *adapter,217 int status, int lock)218{219 u32 val;220 221 if (lock) {222 if (qlcnic_83xx_lock_driver(adapter))223 return -EBUSY;224 }225 226 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);227 228 if (status)229 val = val | (1 << adapter->portnum);230 else231 val = val & ~(1 << adapter->portnum);232 233 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);234 qlcnic_83xx_idc_update_minor_version(adapter);235 236 if (lock)237 qlcnic_83xx_unlock_driver(adapter);238 239 return 0;240}241 242static int qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter *adapter)243{244 u32 val;245 u8 version;246 247 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION);248 version = val & 0xFF;249 250 if (version != QLC_83XX_IDC_MAJOR_VERSION) {251 dev_info(&adapter->pdev->dev,252 "%s:mismatch. version 0x%x, expected version 0x%x\n",253 __func__, version, QLC_83XX_IDC_MAJOR_VERSION);254 return -EIO;255 }256 257 return 0;258}259 260static int qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter *adapter,261 int lock)262{263 u32 val;264 265 if (lock) {266 if (qlcnic_83xx_lock_driver(adapter))267 return -EBUSY;268 }269 270 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, 0);271 /* Clear graceful reset bit */272 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);273 val &= ~QLC_83XX_IDC_GRACEFULL_RESET;274 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);275 276 if (lock)277 qlcnic_83xx_unlock_driver(adapter);278 279 return 0;280}281 282static int qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter *adapter,283 int flag, int lock)284{285 u32 val;286 287 if (lock) {288 if (qlcnic_83xx_lock_driver(adapter))289 return -EBUSY;290 }291 292 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);293 if (flag)294 val = val | (1 << adapter->portnum);295 else296 val = val & ~(1 << adapter->portnum);297 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, val);298 299 if (lock)300 qlcnic_83xx_unlock_driver(adapter);301 302 return 0;303}304 305static int qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter *adapter,306 int time_limit)307{308 u64 seconds;309 310 seconds = jiffies / HZ - adapter->ahw->idc.sec_counter;311 if (seconds <= time_limit)312 return 0;313 else314 return -EBUSY;315}316 317/**318 * qlcnic_83xx_idc_check_reset_ack_reg319 *320 * @adapter: adapter structure321 *322 * Check ACK wait limit and clear the functions which failed to ACK323 *324 * Return 0 if all functions have acknowledged the reset request.325 **/326static int qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter *adapter)327{328 int timeout;329 u32 ack, presence, val;330 331 timeout = QLC_83XX_IDC_RESET_TIMEOUT_SECS;332 ack = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK);333 presence = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);334 dev_info(&adapter->pdev->dev,335 "%s: ack = 0x%x, presence = 0x%x\n", __func__, ack, presence);336 if (!((ack & presence) == presence)) {337 if (qlcnic_83xx_idc_check_timeout(adapter, timeout)) {338 /* Clear functions which failed to ACK */339 dev_info(&adapter->pdev->dev,340 "%s: ACK wait exceeds time limit\n", __func__);341 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);342 val = val & ~(ack ^ presence);343 if (qlcnic_83xx_lock_driver(adapter))344 return -EBUSY;345 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);346 dev_info(&adapter->pdev->dev,347 "%s: updated drv presence reg = 0x%x\n",348 __func__, val);349 qlcnic_83xx_unlock_driver(adapter);350 return 0;351 352 } else {353 return 1;354 }355 } else {356 dev_info(&adapter->pdev->dev,357 "%s: Reset ACK received from all functions\n",358 __func__);359 return 0;360 }361}362 363/**364 * qlcnic_83xx_idc_tx_soft_reset365 *366 * @adapter: adapter structure367 *368 * Handle context deletion and recreation request from transmit routine369 *370 * Returns -EBUSY or Success (0)371 *372 **/373static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter)374{375 struct net_device *netdev = adapter->netdev;376 377 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))378 return -EBUSY;379 380 netif_device_detach(netdev);381 qlcnic_down(adapter, netdev);382 qlcnic_up(adapter, netdev);383 netif_device_attach(netdev);384 clear_bit(__QLCNIC_RESETTING, &adapter->state);385 netdev_info(adapter->netdev, "%s: soft reset complete.\n", __func__);386 387 return 0;388}389 390/**391 * qlcnic_83xx_idc_detach_driver392 *393 * @adapter: adapter structure394 * Detach net interface, stop TX and cleanup resources before the HW reset.395 * Returns: None396 *397 **/398static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)399{400 int i;401 struct net_device *netdev = adapter->netdev;402 403 netif_device_detach(netdev);404 qlcnic_83xx_detach_mailbox_work(adapter);405 406 /* Disable mailbox interrupt */407 qlcnic_83xx_disable_mbx_intr(adapter);408 qlcnic_down(adapter, netdev);409 for (i = 0; i < adapter->ahw->num_msix; i++) {410 adapter->ahw->intr_tbl[i].id = i;411 adapter->ahw->intr_tbl[i].enabled = 0;412 adapter->ahw->intr_tbl[i].src = 0;413 }414 415 if (qlcnic_sriov_pf_check(adapter))416 qlcnic_sriov_pf_reset(adapter);417}418 419/**420 * qlcnic_83xx_idc_attach_driver421 *422 * @adapter: adapter structure423 *424 * Re-attach and re-enable net interface425 * Returns: None426 *427 **/428static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter)429{430 struct net_device *netdev = adapter->netdev;431 432 if (netif_running(netdev)) {433 if (qlcnic_up(adapter, netdev))434 goto done;435 qlcnic_restore_indev_addr(netdev, NETDEV_UP);436 }437done:438 netif_device_attach(netdev);439}440 441static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter,442 int lock)443{444 if (lock) {445 if (qlcnic_83xx_lock_driver(adapter))446 return -EBUSY;447 }448 449 qlcnic_83xx_idc_clear_registers(adapter, 0);450 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_FAILED);451 if (lock)452 qlcnic_83xx_unlock_driver(adapter);453 454 qlcnic_83xx_idc_log_state_history(adapter);455 dev_info(&adapter->pdev->dev, "Device will enter failed state\n");456 457 return 0;458}459 460static int qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter *adapter,461 int lock)462{463 if (lock) {464 if (qlcnic_83xx_lock_driver(adapter))465 return -EBUSY;466 }467 468 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_INIT);469 470 if (lock)471 qlcnic_83xx_unlock_driver(adapter);472 473 return 0;474}475 476static int qlcnic_83xx_idc_enter_need_quiesce(struct qlcnic_adapter *adapter,477 int lock)478{479 if (lock) {480 if (qlcnic_83xx_lock_driver(adapter))481 return -EBUSY;482 }483 484 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,485 QLC_83XX_IDC_DEV_NEED_QUISCENT);486 487 if (lock)488 qlcnic_83xx_unlock_driver(adapter);489 490 return 0;491}492 493static int494qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter *adapter, int lock)495{496 if (lock) {497 if (qlcnic_83xx_lock_driver(adapter))498 return -EBUSY;499 }500 501 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,502 QLC_83XX_IDC_DEV_NEED_RESET);503 504 if (lock)505 qlcnic_83xx_unlock_driver(adapter);506 507 return 0;508}509 510static int qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter *adapter,511 int lock)512{513 if (lock) {514 if (qlcnic_83xx_lock_driver(adapter))515 return -EBUSY;516 }517 518 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_READY);519 if (lock)520 qlcnic_83xx_unlock_driver(adapter);521 522 return 0;523}524 525/**526 * qlcnic_83xx_idc_find_reset_owner_id527 *528 * @adapter: adapter structure529 *530 * NIC gets precedence over ISCSI and ISCSI has precedence over FCOE.531 * Within the same class, function with lowest PCI ID assumes ownership532 *533 * Returns: reset owner id or failure indication (-EIO)534 *535 **/536static int qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter *adapter)537{538 u32 reg, reg1, reg2, i, j, owner, class;539 540 reg1 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_1);541 reg2 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_2);542 owner = QLCNIC_TYPE_NIC;543 i = 0;544 j = 0;545 reg = reg1;546 547 do {548 class = (((reg & (0xF << j * 4)) >> j * 4) & 0x3);549 if (class == owner)550 break;551 if (i == (QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO - 1)) {552 reg = reg2;553 j = 0;554 } else {555 j++;556 }557 558 if (i == (QLC_83XX_IDC_MAX_CNA_FUNCTIONS - 1)) {559 if (owner == QLCNIC_TYPE_NIC)560 owner = QLCNIC_TYPE_ISCSI;561 else if (owner == QLCNIC_TYPE_ISCSI)562 owner = QLCNIC_TYPE_FCOE;563 else if (owner == QLCNIC_TYPE_FCOE)564 return -EIO;565 reg = reg1;566 j = 0;567 i = 0;568 }569 } while (i++ < QLC_83XX_IDC_MAX_CNA_FUNCTIONS);570 571 return i;572}573 574static int qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter *adapter, int lock)575{576 int ret = 0;577 578 ret = qlcnic_83xx_restart_hw(adapter);579 580 if (ret) {581 qlcnic_83xx_idc_enter_failed_state(adapter, lock);582 } else {583 qlcnic_83xx_idc_clear_registers(adapter, lock);584 ret = qlcnic_83xx_idc_enter_ready_state(adapter, lock);585 }586 587 return ret;588}589 590static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)591{592 u32 status;593 594 status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1);595 596 if (status & QLCNIC_RCODE_FATAL_ERROR) {597 dev_err(&adapter->pdev->dev,598 "peg halt status1=0x%x\n", status);599 if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) {600 dev_err(&adapter->pdev->dev,601 "On board active cooling fan failed. "602 "Device has been halted.\n");603 dev_err(&adapter->pdev->dev,604 "Replace the adapter.\n");605 return -EIO;606 }607 }608 609 return 0;610}611 612int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)613{614 int err;615 616 qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);617 qlcnic_83xx_enable_mbx_interrupt(adapter);618 619 qlcnic_83xx_initialize_nic(adapter, 1);620 621 err = qlcnic_sriov_pf_reinit(adapter);622 if (err)623 return err;624 625 qlcnic_83xx_enable_mbx_interrupt(adapter);626 627 if (qlcnic_83xx_configure_opmode(adapter)) {628 qlcnic_83xx_idc_enter_failed_state(adapter, 1);629 return -EIO;630 }631 632 if (adapter->nic_ops->init_driver(adapter)) {633 qlcnic_83xx_idc_enter_failed_state(adapter, 1);634 return -EIO;635 }636 637 if (adapter->portnum == 0)638 qlcnic_set_drv_version(adapter);639 640 qlcnic_dcb_get_info(adapter->dcb);641 qlcnic_83xx_idc_attach_driver(adapter);642 643 return 0;644}645 646static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)647{648 struct qlcnic_hardware_context *ahw = adapter->ahw;649 650 qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);651 qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);652 set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);653 654 ahw->idc.quiesce_req = 0;655 ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;656 ahw->idc.err_code = 0;657 ahw->idc.collect_dump = 0;658 ahw->reset_context = 0;659 adapter->tx_timeo_cnt = 0;660 ahw->idc.delay_reset = 0;661 662 clear_bit(__QLCNIC_RESETTING, &adapter->state);663}664 665/**666 * qlcnic_83xx_idc_ready_state_entry667 *668 * @adapter: adapter structure669 *670 * Perform ready state initialization, this routine will get invoked only671 * once from READY state.672 *673 * Returns: Error code or Success(0)674 *675 **/676int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *adapter)677{678 struct qlcnic_hardware_context *ahw = adapter->ahw;679 680 if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) {681 qlcnic_83xx_idc_update_idc_params(adapter);682 /* Re-attach the device if required */683 if ((ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) ||684 (ahw->idc.prev_state == QLC_83XX_IDC_DEV_INIT)) {685 if (qlcnic_83xx_idc_reattach_driver(adapter))686 return -EIO;687 }688 }689 690 return 0;691}692 693/**694 * qlcnic_83xx_idc_vnic_pf_entry695 *696 * @adapter: adapter structure697 *698 * Ensure vNIC mode privileged function starts only after vNIC mode is699 * enabled by management function.700 * If vNIC mode is ready, start initialization.701 *702 * Returns: -EIO or 0703 *704 **/705int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *adapter)706{707 u32 state;708 struct qlcnic_hardware_context *ahw = adapter->ahw;709 710 /* Privileged function waits till mgmt function enables VNIC mode */711 state = QLCRDX(adapter->ahw, QLC_83XX_VNIC_STATE);712 if (state != QLCNIC_DEV_NPAR_OPER) {713 if (!ahw->idc.vnic_wait_limit--) {714 qlcnic_83xx_idc_enter_failed_state(adapter, 1);715 return -EIO;716 }717 dev_info(&adapter->pdev->dev, "vNIC mode disabled\n");718 return -EIO;719 720 } else {721 /* Perform one time initialization from ready state */722 if (ahw->idc.vnic_state != QLCNIC_DEV_NPAR_OPER) {723 qlcnic_83xx_idc_update_idc_params(adapter);724 725 /* If the previous state is UNKNOWN, device will be726 already attached properly by Init routine*/727 if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_UNKNOWN) {728 if (qlcnic_83xx_idc_reattach_driver(adapter))729 return -EIO;730 }731 adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_OPER;732 dev_info(&adapter->pdev->dev, "vNIC mode enabled\n");733 }734 }735 736 return 0;737}738 739static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)740{741 adapter->ahw->idc.err_code = -EIO;742 dev_err(&adapter->pdev->dev,743 "%s: Device in unknown state\n", __func__);744 clear_bit(__QLCNIC_RESETTING, &adapter->state);745 return 0;746}747 748/**749 * qlcnic_83xx_idc_cold_state_handler750 *751 * @adapter: adapter structure752 *753 * If HW is up and running device will enter READY state.754 * If firmware image from host needs to be loaded, device is755 * forced to start with the file firmware image.756 *757 * Returns: Error code or Success(0)758 *759 **/760static int qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter *adapter)761{762 qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 0);763 qlcnic_83xx_idc_update_audit_reg(adapter, 1, 0);764 765 if (qlcnic_load_fw_file) {766 qlcnic_83xx_idc_restart_hw(adapter, 0);767 } else {768 if (qlcnic_83xx_check_hw_status(adapter)) {769 qlcnic_83xx_idc_enter_failed_state(adapter, 0);770 return -EIO;771 } else {772 qlcnic_83xx_idc_enter_ready_state(adapter, 0);773 }774 }775 return 0;776}777 778/**779 * qlcnic_83xx_idc_init_state780 *781 * @adapter: adapter structure782 *783 * Reset owner will restart the device from this state.784 * Device will enter failed state if it remains785 * in this state for more than DEV_INIT time limit.786 *787 * Returns: Error code or Success(0)788 *789 **/790static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)791{792 int timeout, ret = 0;793 u32 owner;794 795 timeout = QLC_83XX_IDC_INIT_TIMEOUT_SECS;796 if (adapter->ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) {797 owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);798 if (adapter->ahw->pci_func == owner)799 ret = qlcnic_83xx_idc_restart_hw(adapter, 1);800 } else {801 ret = qlcnic_83xx_idc_check_timeout(adapter, timeout);802 }803 804 return ret;805}806 807/**808 * qlcnic_83xx_idc_ready_state809 *810 * @adapter: adapter structure811 *812 * Perform IDC protocol specicifed actions after monitoring device state and813 * events.814 *815 * Returns: Error code or Success(0)816 *817 **/818static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)819{820 struct qlcnic_hardware_context *ahw = adapter->ahw;821 struct qlcnic_mailbox *mbx = ahw->mailbox;822 int ret = 0;823 u32 val;824 825 /* Perform NIC configuration based ready state entry actions */826 if (ahw->idc.state_entry(adapter))827 return -EIO;828 829 if (qlcnic_check_temp(adapter)) {830 if (ahw->temp == QLCNIC_TEMP_PANIC) {831 qlcnic_83xx_idc_check_fan_failure(adapter);832 dev_err(&adapter->pdev->dev,833 "Error: device temperature %d above limits\n",834 adapter->ahw->temp);835 clear_bit(QLC_83XX_MBX_READY, &mbx->status);836 set_bit(__QLCNIC_RESETTING, &adapter->state);837 qlcnic_83xx_idc_detach_driver(adapter);838 qlcnic_83xx_idc_enter_failed_state(adapter, 1);839 return -EIO;840 }841 }842 843 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);844 ret = qlcnic_83xx_check_heartbeat(adapter);845 if (ret) {846 adapter->flags |= QLCNIC_FW_HANG;847 if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {848 clear_bit(QLC_83XX_MBX_READY, &mbx->status);849 set_bit(__QLCNIC_RESETTING, &adapter->state);850 qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);851 } else {852 netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",853 __func__);854 qlcnic_83xx_idc_enter_failed_state(adapter, 1);855 }856 return -EIO;857 }858 859 if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {860 clear_bit(QLC_83XX_MBX_READY, &mbx->status);861 862 /* Move to need reset state and prepare for reset */863 qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);864 return ret;865 }866 867 /* Check for soft reset request */868 if (ahw->reset_context &&869 !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {870 adapter->ahw->reset_context = 0;871 qlcnic_83xx_idc_tx_soft_reset(adapter);872 return ret;873 }874 875 /* Move to need quiesce state if requested */876 if (adapter->ahw->idc.quiesce_req) {877 qlcnic_83xx_idc_enter_need_quiesce(adapter, 1);878 qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);879 return ret;880 }881 882 return ret;883}884 885/**886 * qlcnic_83xx_idc_need_reset_state887 *888 * @adapter: adapter structure889 *890 * Device will remain in this state until:891 * Reset request ACK's are received from all the functions892 * Wait time exceeds max time limit893 *894 * Returns: Error code or Success(0)895 *896 **/897static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)898{899 struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;900 int ret = 0;901 902 if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {903 qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);904 set_bit(__QLCNIC_RESETTING, &adapter->state);905 clear_bit(QLC_83XX_MBX_READY, &mbx->status);906 if (adapter->ahw->nic_mode == QLCNIC_VNIC_MODE)907 qlcnic_83xx_disable_vnic_mode(adapter, 1);908 909 if (qlcnic_check_diag_status(adapter)) {910 dev_info(&adapter->pdev->dev,911 "%s: Wait for diag completion\n", __func__);912 adapter->ahw->idc.delay_reset = 1;913 return 0;914 } else {915 qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);916 qlcnic_83xx_idc_detach_driver(adapter);917 }918 }919 920 if (qlcnic_check_diag_status(adapter)) {921 dev_info(&adapter->pdev->dev,922 "%s: Wait for diag completion\n", __func__);923 return -1;924 } else {925 if (adapter->ahw->idc.delay_reset) {926 qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);927 qlcnic_83xx_idc_detach_driver(adapter);928 adapter->ahw->idc.delay_reset = 0;929 }930 931 /* Check for ACK from other functions */932 ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);933 if (ret) {934 dev_info(&adapter->pdev->dev,935 "%s: Waiting for reset ACK\n", __func__);936 return -1;937 }938 }939 940 /* Transit to INIT state and restart the HW */941 qlcnic_83xx_idc_enter_init_state(adapter, 1);942 943 return ret;944}945 946static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)947{948 dev_err(&adapter->pdev->dev, "%s: TBD\n", __func__);949 return 0;950}951 952static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)953{954 struct qlcnic_hardware_context *ahw = adapter->ahw;955 u32 val, owner;956 957 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);958 if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {959 owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);960 if (ahw->pci_func == owner) {961 qlcnic_83xx_stop_hw(adapter);962 qlcnic_dump_fw(adapter);963 }964 }965 966 netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",967 __func__);968 clear_bit(__QLCNIC_RESETTING, &adapter->state);969 ahw->idc.err_code = -EIO;970 971 return;972}973 974static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)975{976 dev_info(&adapter->pdev->dev, "%s: TBD\n", __func__);977 return 0;978}979 980static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter,981 u32 state)982{983 u32 cur, prev, next;984 985 cur = adapter->ahw->idc.curr_state;986 prev = adapter->ahw->idc.prev_state;987 next = state;988 989 if ((next < QLC_83XX_IDC_DEV_COLD) ||990 (next > QLC_83XX_IDC_DEV_QUISCENT)) {991 dev_err(&adapter->pdev->dev,992 "%s: curr %d, prev %d, next state %d is invalid\n",993 __func__, cur, prev, state);994 return 1;995 }996 997 if ((cur == QLC_83XX_IDC_DEV_UNKNOWN) &&998 (prev == QLC_83XX_IDC_DEV_UNKNOWN)) {999 if ((next != QLC_83XX_IDC_DEV_COLD) &&1000 (next != QLC_83XX_IDC_DEV_READY)) {1001 dev_err(&adapter->pdev->dev,1002 "%s: failed, cur %d prev %d next %d\n",1003 __func__, cur, prev, next);1004 return 1;1005 }1006 }1007 1008 if (next == QLC_83XX_IDC_DEV_INIT) {1009 if ((prev != QLC_83XX_IDC_DEV_INIT) &&1010 (prev != QLC_83XX_IDC_DEV_COLD) &&1011 (prev != QLC_83XX_IDC_DEV_NEED_RESET)) {1012 dev_err(&adapter->pdev->dev,1013 "%s: failed, cur %d prev %d next %d\n",1014 __func__, cur, prev, next);1015 return 1;1016 }1017 }1018 1019 return 0;1020}1021 1022#define QLC_83XX_ENCAP_TYPE_VXLAN BIT_11023#define QLC_83XX_MATCH_ENCAP_ID BIT_21024#define QLC_83XX_SET_VXLAN_UDP_DPORT BIT_31025#define QLC_83XX_VXLAN_UDP_DPORT(PORT) ((PORT & 0xffff) << 16)1026 1027#define QLCNIC_ENABLE_INGRESS_ENCAP_PARSING 11028#define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 01029 1030int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter, u16 port)1031{1032 struct qlcnic_cmd_args cmd;1033 int ret = 0;1034 1035 memset(&cmd, 0, sizeof(cmd));1036 1037 ret = qlcnic_alloc_mbx_args(&cmd, adapter,1038 QLCNIC_CMD_INIT_NIC_FUNC);1039 if (ret)1040 return ret;1041 1042 cmd.req.arg[1] = QLC_83XX_MULTI_TENANCY_INFO;1043 cmd.req.arg[2] = QLC_83XX_ENCAP_TYPE_VXLAN |1044 QLC_83XX_SET_VXLAN_UDP_DPORT |1045 QLC_83XX_VXLAN_UDP_DPORT(port);1046 1047 ret = qlcnic_issue_cmd(adapter, &cmd);1048 if (ret)1049 netdev_err(adapter->netdev,1050 "Failed to set VXLAN port %d in adapter\n",1051 port);1052 1053 qlcnic_free_mbx_args(&cmd);1054 1055 return ret;1056}1057 1058int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port)1059{1060 struct qlcnic_cmd_args cmd;1061 int ret = 0;1062 1063 memset(&cmd, 0, sizeof(cmd));1064 1065 ret = qlcnic_alloc_mbx_args(&cmd, adapter,1066 QLCNIC_CMD_SET_INGRESS_ENCAP);1067 if (ret)1068 return ret;1069 1070 cmd.req.arg[1] = port ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING :1071 QLCNIC_DISABLE_INGRESS_ENCAP_PARSING;1072 1073 ret = qlcnic_issue_cmd(adapter, &cmd);1074 if (ret)1075 netdev_err(adapter->netdev,1076 "Failed to %s VXLAN parsing for port %d\n",1077 port ? "enable" : "disable", port);1078 else1079 netdev_info(adapter->netdev,1080 "%s VXLAN parsing for port %d\n",1081 port ? "Enabled" : "Disabled", port);1082 1083 qlcnic_free_mbx_args(&cmd);1084 1085 return ret;1086}1087 1088static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter)1089{1090 if (adapter->fhash.fnum)1091 qlcnic_prune_lb_filters(adapter);1092}1093 1094/**1095 * qlcnic_83xx_idc_poll_dev_state1096 *1097 * @work: kernel work queue structure used to schedule the function1098 *1099 * Poll device state periodically and perform state specific1100 * actions defined by Inter Driver Communication (IDC) protocol.1101 *1102 * Returns: None1103 *1104 **/1105void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)1106{1107 struct qlcnic_adapter *adapter;1108 u32 state;1109 1110 adapter = container_of(work, struct qlcnic_adapter, fw_work.work);1111 state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);1112 1113 if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {1114 qlcnic_83xx_idc_log_state_history(adapter);1115 adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;1116 } else {1117 adapter->ahw->idc.curr_state = state;1118 }1119 1120 switch (adapter->ahw->idc.curr_state) {1121 case QLC_83XX_IDC_DEV_READY:1122 qlcnic_83xx_idc_ready_state(adapter);1123 break;1124 case QLC_83XX_IDC_DEV_NEED_RESET:1125 qlcnic_83xx_idc_need_reset_state(adapter);1126 break;1127 case QLC_83XX_IDC_DEV_NEED_QUISCENT:1128 qlcnic_83xx_idc_need_quiesce_state(adapter);1129 break;1130 case QLC_83XX_IDC_DEV_FAILED:1131 qlcnic_83xx_idc_failed_state(adapter);1132 return;1133 case QLC_83XX_IDC_DEV_INIT:1134 qlcnic_83xx_idc_init_state(adapter);1135 break;1136 case QLC_83XX_IDC_DEV_QUISCENT:1137 qlcnic_83xx_idc_quiesce_state(adapter);1138 break;1139 default:1140 qlcnic_83xx_idc_unknown_state(adapter);1141 return;1142 }1143 adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;1144 qlcnic_83xx_periodic_tasks(adapter);1145 1146 /* Re-schedule the function */1147 if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))1148 qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,1149 adapter->ahw->idc.delay);1150}1151 1152static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)1153{1154 u32 idc_params, val;1155 1156 if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR,1157 (u8 *)&idc_params, 1)) {1158 dev_info(&adapter->pdev->dev,1159 "%s:failed to get IDC params from flash\n", __func__);1160 adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS;1161 adapter->reset_ack_timeo = QLC_83XX_IDC_RESET_TIMEOUT_SECS;1162 } else {1163 adapter->dev_init_timeo = idc_params & 0xFFFF;1164 adapter->reset_ack_timeo = ((idc_params >> 16) & 0xFFFF);1165 }1166 1167 adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN;1168 adapter->ahw->idc.prev_state = QLC_83XX_IDC_DEV_UNKNOWN;1169 adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY;1170 adapter->ahw->idc.err_code = 0;1171 adapter->ahw->idc.collect_dump = 0;1172 adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;1173 1174 clear_bit(__QLCNIC_RESETTING, &adapter->state);1175 set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);1176 1177 /* Check if reset recovery is disabled */1178 if (!qlcnic_auto_fw_reset) {1179 /* Propagate do not reset request to other functions */1180 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1181 val = val | QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;1182 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1183 }1184}1185 1186static int1187qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter)1188{1189 u32 state, val;1190 1191 if (qlcnic_83xx_lock_driver(adapter))1192 return -EIO;1193 1194 /* Clear driver lock register */1195 QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, 0);1196 if (qlcnic_83xx_idc_update_major_version(adapter, 0)) {1197 qlcnic_83xx_unlock_driver(adapter);1198 return -EIO;1199 }1200 1201 state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE);1202 if (qlcnic_83xx_idc_check_state_validity(adapter, state)) {1203 qlcnic_83xx_unlock_driver(adapter);1204 return -EIO;1205 }1206 1207 if (state != QLC_83XX_IDC_DEV_COLD && qlcnic_load_fw_file) {1208 QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE,1209 QLC_83XX_IDC_DEV_COLD);1210 state = QLC_83XX_IDC_DEV_COLD;1211 }1212 1213 adapter->ahw->idc.curr_state = state;1214 /* First to load function should cold boot the device */1215 if (state == QLC_83XX_IDC_DEV_COLD)1216 qlcnic_83xx_idc_cold_state_handler(adapter);1217 1218 /* Check if reset recovery is enabled */1219 if (qlcnic_auto_fw_reset) {1220 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1221 val = val & ~QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY;1222 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1223 }1224 1225 qlcnic_83xx_unlock_driver(adapter);1226 1227 return 0;1228}1229 1230int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)1231{1232 int ret = -EIO;1233 1234 qlcnic_83xx_setup_idc_parameters(adapter);1235 1236 if (qlcnic_83xx_get_reset_instruction_template(adapter))1237 return ret;1238 1239 if (!qlcnic_83xx_idc_check_driver_presence_reg(adapter)) {1240 if (qlcnic_83xx_idc_first_to_load_function_handler(adapter))1241 return -EIO;1242 } else {1243 if (qlcnic_83xx_idc_check_major_version(adapter))1244 return -EIO;1245 }1246 1247 qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);1248 1249 return 0;1250}1251 1252void qlcnic_83xx_idc_exit(struct qlcnic_adapter *adapter)1253{1254 int id;1255 u32 val;1256 1257 while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))1258 usleep_range(10000, 11000);1259 1260 id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);1261 id = id & 0xFF;1262 1263 if (id == adapter->portnum) {1264 dev_err(&adapter->pdev->dev,1265 "%s: wait for lock recovery.. %d\n", __func__, id);1266 msleep(20);1267 id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);1268 id = id & 0xFF;1269 }1270 1271 /* Clear driver presence bit */1272 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);1273 val = val & ~(1 << adapter->portnum);1274 QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val);1275 clear_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);1276 clear_bit(__QLCNIC_RESETTING, &adapter->state);1277 1278 cancel_delayed_work_sync(&adapter->fw_work);1279}1280 1281void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)1282{1283 u32 val;1284 1285 if (qlcnic_sriov_vf_check(adapter))1286 return;1287 1288 if (qlcnic_83xx_lock_driver(adapter)) {1289 dev_err(&adapter->pdev->dev,1290 "%s:failed, please retry\n", __func__);1291 return;1292 }1293 1294 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1295 if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {1296 netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",1297 __func__);1298 qlcnic_83xx_idc_enter_failed_state(adapter, 0);1299 qlcnic_83xx_unlock_driver(adapter);1300 return;1301 }1302 1303 if (key == QLCNIC_FORCE_FW_RESET) {1304 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);1305 val = val | QLC_83XX_IDC_GRACEFULL_RESET;1306 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);1307 } else if (key == QLCNIC_FORCE_FW_DUMP_KEY) {1308 adapter->ahw->idc.collect_dump = 1;1309 }1310 1311 qlcnic_83xx_unlock_driver(adapter);1312 return;1313}1314 1315static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)1316{1317 u8 *p_cache;1318 u32 src, size;1319 u64 dest;1320 int ret = -EIO;1321 1322 src = QLC_83XX_BOOTLOADER_FLASH_ADDR;1323 dest = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_ADDR);1324 size = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_SIZE);1325 1326 /* alignment check */1327 if (size & 0xF)1328 size = (size + 16) & ~0xF;1329 1330 p_cache = vzalloc(size);1331 if (p_cache == NULL)1332 return -ENOMEM;1333 1334 ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,1335 size / sizeof(u32));1336 if (ret) {1337 vfree(p_cache);1338 return ret;1339 }1340 /* 16 byte write to MS memory */1341 ret = qlcnic_ms_mem_write128(adapter, dest, (u32 *)p_cache,1342 size / 16);1343 if (ret) {1344 vfree(p_cache);1345 return ret;1346 }1347 vfree(p_cache);1348 1349 return ret;1350}1351 1352static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)1353{1354 struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;1355 const struct firmware *fw = fw_info->fw;1356 u32 dest, *p_cache, *temp;1357 __le32 *temp_le;1358 u8 data[16];1359 size_t size;1360 int i, ret;1361 u64 addr;1362 1363 temp = vzalloc(fw->size);1364 if (!temp) {1365 release_firmware(fw);1366 fw_info->fw = NULL;1367 return -ENOMEM;1368 }1369 1370 temp_le = (__le32 *)fw->data;1371 1372 /* FW image in file is in little endian, swap the data to nullify1373 * the effect of writel() operation on big endian platform.1374 */1375 for (i = 0; i < fw->size / sizeof(u32); i++)1376 temp[i] = __le32_to_cpu(temp_le[i]);1377 1378 dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);1379 size = (fw->size & ~0xF);1380 p_cache = temp;1381 addr = (u64)dest;1382 1383 ret = qlcnic_ms_mem_write128(adapter, addr,1384 p_cache, size / 16);1385 if (ret) {1386 dev_err(&adapter->pdev->dev, "MS memory write failed\n");1387 goto exit;1388 }1389 1390 /* alignment check */1391 if (fw->size & 0xF) {1392 addr = dest + size;1393 for (i = 0; i < (fw->size & 0xF); i++)1394 data[i] = ((u8 *)temp)[size + i];1395 for (; i < 16; i++)1396 data[i] = 0;1397 ret = qlcnic_ms_mem_write128(adapter, addr,1398 (u32 *)data, 1);1399 if (ret) {1400 dev_err(&adapter->pdev->dev,1401 "MS memory write failed\n");1402 goto exit;1403 }1404 }1405 1406exit:1407 release_firmware(fw);1408 fw_info->fw = NULL;1409 vfree(temp);1410 1411 return ret;1412}1413 1414static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)1415{1416 int i, j;1417 u32 val = 0, val1 = 0, reg = 0;1418 int err = 0;1419 1420 val = QLCRD32(adapter, QLC_83XX_SRE_SHIM_REG, &err);1421 if (err == -EIO)1422 return;1423 dev_info(&adapter->pdev->dev, "SRE-Shim Ctrl:0x%x\n", val);1424 1425 for (j = 0; j < 2; j++) {1426 if (j == 0) {1427 dev_info(&adapter->pdev->dev,1428 "Port 0 RxB Pause Threshold Regs[TC7..TC0]:");1429 reg = QLC_83XX_PORT0_THRESHOLD;1430 } else if (j == 1) {1431 dev_info(&adapter->pdev->dev,1432 "Port 1 RxB Pause Threshold Regs[TC7..TC0]:");1433 reg = QLC_83XX_PORT1_THRESHOLD;1434 }1435 for (i = 0; i < 8; i++) {1436 val = QLCRD32(adapter, reg + (i * 0x4), &err);1437 if (err == -EIO)1438 return;1439 dev_info(&adapter->pdev->dev, "0x%x ", val);1440 }1441 dev_info(&adapter->pdev->dev, "\n");1442 }1443 1444 for (j = 0; j < 2; j++) {1445 if (j == 0) {1446 dev_info(&adapter->pdev->dev,1447 "Port 0 RxB TC Max Cell Registers[4..1]:");1448 reg = QLC_83XX_PORT0_TC_MC_REG;1449 } else if (j == 1) {1450 dev_info(&adapter->pdev->dev,1451 "Port 1 RxB TC Max Cell Registers[4..1]:");1452 reg = QLC_83XX_PORT1_TC_MC_REG;1453 }1454 for (i = 0; i < 4; i++) {1455 val = QLCRD32(adapter, reg + (i * 0x4), &err);1456 if (err == -EIO)1457 return;1458 dev_info(&adapter->pdev->dev, "0x%x ", val);1459 }1460 dev_info(&adapter->pdev->dev, "\n");1461 }1462 1463 for (j = 0; j < 2; j++) {1464 if (j == 0) {1465 dev_info(&adapter->pdev->dev,1466 "Port 0 RxB Rx TC Stats[TC7..TC0]:");1467 reg = QLC_83XX_PORT0_TC_STATS;1468 } else if (j == 1) {1469 dev_info(&adapter->pdev->dev,1470 "Port 1 RxB Rx TC Stats[TC7..TC0]:");1471 reg = QLC_83XX_PORT1_TC_STATS;1472 }1473 for (i = 7; i >= 0; i--) {1474 val = QLCRD32(adapter, reg, &err);1475 if (err == -EIO)1476 return;1477 val &= ~(0x7 << 29); /* Reset bits 29 to 31 */1478 QLCWR32(adapter, reg, (val | (i << 29)));1479 val = QLCRD32(adapter, reg, &err);1480 if (err == -EIO)1481 return;1482 dev_info(&adapter->pdev->dev, "0x%x ", val);1483 }1484 dev_info(&adapter->pdev->dev, "\n");1485 }1486 1487 val = QLCRD32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, &err);1488 if (err == -EIO)1489 return;1490 val1 = QLCRD32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, &err);1491 if (err == -EIO)1492 return;1493 dev_info(&adapter->pdev->dev,1494 "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",1495 val, val1);1496}1497 1498 1499static void qlcnic_83xx_disable_pause_frames(struct qlcnic_adapter *adapter)1500{1501 u32 reg = 0, i, j;1502 1503 if (qlcnic_83xx_lock_driver(adapter)) {1504 dev_err(&adapter->pdev->dev,1505 "%s:failed to acquire driver lock\n", __func__);1506 return;1507 }1508 1509 qlcnic_83xx_dump_pause_control_regs(adapter);1510 QLCWR32(adapter, QLC_83XX_SRE_SHIM_REG, 0x0);1511 1512 for (j = 0; j < 2; j++) {1513 if (j == 0)1514 reg = QLC_83XX_PORT0_THRESHOLD;1515 else if (j == 1)1516 reg = QLC_83XX_PORT1_THRESHOLD;1517 1518 for (i = 0; i < 8; i++)1519 QLCWR32(adapter, reg + (i * 0x4), 0x0);1520 }1521 1522 for (j = 0; j < 2; j++) {1523 if (j == 0)1524 reg = QLC_83XX_PORT0_TC_MC_REG;1525 else if (j == 1)1526 reg = QLC_83XX_PORT1_TC_MC_REG;1527 1528 for (i = 0; i < 4; i++)1529 QLCWR32(adapter, reg + (i * 0x4), 0x03FF03FF);1530 }1531 1532 QLCWR32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, 0);1533 QLCWR32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, 0);1534 dev_info(&adapter->pdev->dev,1535 "Disabled pause frames successfully on all ports\n");1536 qlcnic_83xx_unlock_driver(adapter);1537}1538 1539static void qlcnic_83xx_take_eport_out_of_reset(struct qlcnic_adapter *adapter)1540{1541 QLCWR32(adapter, QLC_83XX_RESET_REG, 0);1542 QLCWR32(adapter, QLC_83XX_RESET_PORT0, 0);1543 QLCWR32(adapter, QLC_83XX_RESET_PORT1, 0);1544 QLCWR32(adapter, QLC_83XX_RESET_PORT2, 0);1545 QLCWR32(adapter, QLC_83XX_RESET_PORT3, 0);1546 QLCWR32(adapter, QLC_83XX_RESET_SRESHIM, 0);1547 QLCWR32(adapter, QLC_83XX_RESET_EPGSHIM, 0);1548 QLCWR32(adapter, QLC_83XX_RESET_ETHERPCS, 0);1549 QLCWR32(adapter, QLC_83XX_RESET_CONTROL, 1);1550}1551 1552static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev)1553{1554 u32 heartbeat, peg_status;1555 int retries, ret = -EIO, err = 0;1556 1557 retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;1558 p_dev->heartbeat = QLC_SHARED_REG_RD32(p_dev,1559 QLCNIC_PEG_ALIVE_COUNTER);1560 1561 do {1562 msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);1563 heartbeat = QLC_SHARED_REG_RD32(p_dev,1564 QLCNIC_PEG_ALIVE_COUNTER);1565 if (heartbeat != p_dev->heartbeat) {1566 ret = QLCNIC_RCODE_SUCCESS;1567 break;1568 }1569 } while (--retries);1570 1571 if (ret) {1572 dev_err(&p_dev->pdev->dev, "firmware hang detected\n");1573 qlcnic_83xx_take_eport_out_of_reset(p_dev);1574 qlcnic_83xx_disable_pause_frames(p_dev);1575 peg_status = QLC_SHARED_REG_RD32(p_dev,1576 QLCNIC_PEG_HALT_STATUS1);1577 dev_info(&p_dev->pdev->dev, "Dumping HW/FW registers\n"1578 "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"1579 "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"1580 "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"1581 "PEG_NET_4_PC: 0x%x\n", peg_status,1582 QLC_SHARED_REG_RD32(p_dev, QLCNIC_PEG_HALT_STATUS2),1583 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_0, &err),1584 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_1, &err),1585 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_2, &err),1586 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_3, &err),1587 QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_4, &err));1588 1589 if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)1590 dev_err(&p_dev->pdev->dev,1591 "Device is being reset err code 0x00006700.\n");1592 }1593 1594 return ret;1595}1596 1597static int qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter *p_dev)1598{1599 int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;1600 u32 val;1601 1602 do {1603 val = QLC_SHARED_REG_RD32(p_dev, QLCNIC_CMDPEG_STATE);1604 if (val == QLC_83XX_CMDPEG_COMPLETE)1605 return 0;1606 msleep(QLCNIC_CMDPEG_CHECK_DELAY);1607 } while (--retries);1608 1609 dev_err(&p_dev->pdev->dev, "%s: failed, state = 0x%x\n", __func__, val);1610 return -EIO;1611}1612 1613static int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev)1614{1615 int err;1616 1617 err = qlcnic_83xx_check_cmd_peg_status(p_dev);1618 if (err)1619 return err;1620 1621 err = qlcnic_83xx_check_heartbeat(p_dev);1622 if (err)1623 return err;1624 1625 return err;1626}1627 1628static int qlcnic_83xx_poll_reg(struct qlcnic_adapter *p_dev, u32 addr,1629 int duration, u32 mask, u32 status)1630{1631 int timeout_error, err = 0;1632 u32 value;1633 u8 retries;1634 1635 value = QLCRD32(p_dev, addr, &err);1636 if (err == -EIO)1637 return err;1638 retries = duration / 10;1639 1640 do {1641 if ((value & mask) != status) {1642 timeout_error = 1;1643 msleep(duration / 10);1644 value = QLCRD32(p_dev, addr, &err);1645 if (err == -EIO)1646 return err;1647 } else {1648 timeout_error = 0;1649 break;1650 }1651 } while (retries--);1652 1653 if (timeout_error) {1654 p_dev->ahw->reset.seq_error++;1655 dev_err(&p_dev->pdev->dev,1656 "%s: Timeout Err, entry_num = %d\n",1657 __func__, p_dev->ahw->reset.seq_index);1658 dev_err(&p_dev->pdev->dev,1659 "0x%08x 0x%08x 0x%08x\n",1660 value, mask, status);1661 }1662 1663 return timeout_error;1664}1665 1666static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev)1667{1668 u32 sum = 0;1669 u16 *buff = (u16 *)p_dev->ahw->reset.buff;1670 int count = p_dev->ahw->reset.hdr->size / sizeof(u16);1671 1672 while (count-- > 0)1673 sum += *buff++;1674 1675 while (sum >> 16)1676 sum = (sum & 0xFFFF) + (sum >> 16);1677 1678 if (~sum) {1679 return 0;1680 } else {1681 dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);1682 return -1;1683 }1684}1685 1686static int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)1687{1688 struct qlcnic_hardware_context *ahw = p_dev->ahw;1689 u32 addr, count, prev_ver, curr_ver;1690 u8 *p_buff;1691 1692 if (ahw->reset.buff != NULL) {1693 prev_ver = p_dev->fw_version;1694 curr_ver = qlcnic_83xx_get_fw_version(p_dev);1695 if (curr_ver > prev_ver)1696 kfree(ahw->reset.buff);1697 else1698 return 0;1699 }1700 1701 ahw->reset.seq_error = 0;1702 ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);1703 if (ahw->reset.buff == NULL)1704 return -ENOMEM;1705 1706 p_buff = p_dev->ahw->reset.buff;1707 addr = QLC_83XX_RESET_TEMPLATE_ADDR;1708 count = sizeof(struct qlc_83xx_reset_hdr) / sizeof(u32);1709 1710 /* Copy template header from flash */1711 if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {1712 dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);1713 return -EIO;1714 }1715 ahw->reset.hdr = (struct qlc_83xx_reset_hdr *)ahw->reset.buff;1716 addr = QLC_83XX_RESET_TEMPLATE_ADDR + ahw->reset.hdr->hdr_size;1717 p_buff = ahw->reset.buff + ahw->reset.hdr->hdr_size;1718 count = (ahw->reset.hdr->size - ahw->reset.hdr->hdr_size) / sizeof(u32);1719 1720 /* Copy rest of the template */1721 if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) {1722 dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__);1723 return -EIO;1724 }1725 1726 if (qlcnic_83xx_reset_template_checksum(p_dev))1727 return -EIO;1728 /* Get Stop, Start and Init command offsets */1729 ahw->reset.init_offset = ahw->reset.buff + ahw->reset.hdr->init_offset;1730 ahw->reset.start_offset = ahw->reset.buff +1731 ahw->reset.hdr->start_offset;1732 ahw->reset.stop_offset = ahw->reset.buff + ahw->reset.hdr->hdr_size;1733 return 0;1734}1735 1736/* Read Write HW register command */1737static void qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter *p_dev,1738 u32 raddr, u32 waddr)1739{1740 int err = 0;1741 u32 value;1742 1743 value = QLCRD32(p_dev, raddr, &err);1744 if (err == -EIO)1745 return;1746 qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);1747}1748 1749/* Read Modify Write HW register command */1750static void qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter *p_dev,1751 u32 raddr, u32 waddr,1752 struct qlc_83xx_rmw *p_rmw_hdr)1753{1754 int err = 0;1755 u32 value;1756 1757 if (p_rmw_hdr->index_a) {1758 value = p_dev->ahw->reset.array[p_rmw_hdr->index_a];1759 } else {1760 value = QLCRD32(p_dev, raddr, &err);1761 if (err == -EIO)1762 return;1763 }1764 1765 value &= p_rmw_hdr->mask;1766 value <<= p_rmw_hdr->shl;1767 value >>= p_rmw_hdr->shr;1768 value |= p_rmw_hdr->or_value;1769 value ^= p_rmw_hdr->xor_value;1770 qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value);1771}1772 1773/* Write HW register command */1774static void qlcnic_83xx_write_list(struct qlcnic_adapter *p_dev,1775 struct qlc_83xx_entry_hdr *p_hdr)1776{1777 int i;1778 struct qlc_83xx_entry *entry;1779 1780 entry = (struct qlc_83xx_entry *)((char *)p_hdr +1781 sizeof(struct qlc_83xx_entry_hdr));1782 1783 for (i = 0; i < p_hdr->count; i++, entry++) {1784 qlcnic_83xx_wrt_reg_indirect(p_dev, entry->arg1,1785 entry->arg2);1786 if (p_hdr->delay)1787 udelay((u32)(p_hdr->delay));1788 }1789}1790 1791/* Read and Write instruction */1792static void qlcnic_83xx_read_write_list(struct qlcnic_adapter *p_dev,1793 struct qlc_83xx_entry_hdr *p_hdr)1794{1795 int i;1796 struct qlc_83xx_entry *entry;1797 1798 entry = (struct qlc_83xx_entry *)((char *)p_hdr +1799 sizeof(struct qlc_83xx_entry_hdr));1800 1801 for (i = 0; i < p_hdr->count; i++, entry++) {1802 qlcnic_83xx_read_write_crb_reg(p_dev, entry->arg1,1803 entry->arg2);1804 if (p_hdr->delay)1805 udelay((u32)(p_hdr->delay));1806 }1807}1808 1809/* Poll HW register command */1810static void qlcnic_83xx_poll_list(struct qlcnic_adapter *p_dev,1811 struct qlc_83xx_entry_hdr *p_hdr)1812{1813 long delay;1814 struct qlc_83xx_entry *entry;1815 struct qlc_83xx_poll *poll;1816 int i, err = 0;1817 unsigned long arg1, arg2;1818 1819 poll = (struct qlc_83xx_poll *)((char *)p_hdr +1820 sizeof(struct qlc_83xx_entry_hdr));1821 1822 entry = (struct qlc_83xx_entry *)((char *)poll +1823 sizeof(struct qlc_83xx_poll));1824 delay = (long)p_hdr->delay;1825 1826 if (!delay) {1827 for (i = 0; i < p_hdr->count; i++, entry++)1828 qlcnic_83xx_poll_reg(p_dev, entry->arg1,1829 delay, poll->mask,1830 poll->status);1831 } else {1832 for (i = 0; i < p_hdr->count; i++, entry++) {1833 arg1 = entry->arg1;1834 arg2 = entry->arg2;1835 if (delay) {1836 if (qlcnic_83xx_poll_reg(p_dev,1837 arg1, delay,1838 poll->mask,1839 poll->status)){1840 QLCRD32(p_dev, arg1, &err);1841 if (err == -EIO)1842 return;1843 QLCRD32(p_dev, arg2, &err);1844 if (err == -EIO)1845 return;1846 }1847 }1848 }1849 }1850}1851 1852/* Poll and write HW register command */1853static void qlcnic_83xx_poll_write_list(struct qlcnic_adapter *p_dev,1854 struct qlc_83xx_entry_hdr *p_hdr)1855{1856 int i;1857 long delay;1858 struct qlc_83xx_quad_entry *entry;1859 struct qlc_83xx_poll *poll;1860 1861 poll = (struct qlc_83xx_poll *)((char *)p_hdr +1862 sizeof(struct qlc_83xx_entry_hdr));1863 entry = (struct qlc_83xx_quad_entry *)((char *)poll +1864 sizeof(struct qlc_83xx_poll));1865 delay = (long)p_hdr->delay;1866 1867 for (i = 0; i < p_hdr->count; i++, entry++) {1868 qlcnic_83xx_wrt_reg_indirect(p_dev, entry->dr_addr,1869 entry->dr_value);1870 qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,1871 entry->ar_value);1872 if (delay)1873 qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,1874 poll->mask, poll->status);1875 }1876}1877 1878/* Read Modify Write register command */1879static void qlcnic_83xx_read_modify_write(struct qlcnic_adapter *p_dev,1880 struct qlc_83xx_entry_hdr *p_hdr)1881{1882 int i;1883 struct qlc_83xx_entry *entry;1884 struct qlc_83xx_rmw *rmw_hdr;1885 1886 rmw_hdr = (struct qlc_83xx_rmw *)((char *)p_hdr +1887 sizeof(struct qlc_83xx_entry_hdr));1888 1889 entry = (struct qlc_83xx_entry *)((char *)rmw_hdr +1890 sizeof(struct qlc_83xx_rmw));1891 1892 for (i = 0; i < p_hdr->count; i++, entry++) {1893 qlcnic_83xx_rmw_crb_reg(p_dev, entry->arg1,1894 entry->arg2, rmw_hdr);1895 if (p_hdr->delay)1896 udelay((u32)(p_hdr->delay));1897 }1898}1899 1900static void qlcnic_83xx_pause(struct qlc_83xx_entry_hdr *p_hdr)1901{1902 if (p_hdr->delay)1903 mdelay((u32)((long)p_hdr->delay));1904}1905 1906/* Read and poll register command */1907static void qlcnic_83xx_poll_read_list(struct qlcnic_adapter *p_dev,1908 struct qlc_83xx_entry_hdr *p_hdr)1909{1910 long delay;1911 int index, i, j, err;1912 struct qlc_83xx_quad_entry *entry;1913 struct qlc_83xx_poll *poll;1914 unsigned long addr;1915 1916 poll = (struct qlc_83xx_poll *)((char *)p_hdr +1917 sizeof(struct qlc_83xx_entry_hdr));1918 1919 entry = (struct qlc_83xx_quad_entry *)((char *)poll +1920 sizeof(struct qlc_83xx_poll));1921 delay = (long)p_hdr->delay;1922 1923 for (i = 0; i < p_hdr->count; i++, entry++) {1924 qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr,1925 entry->ar_value);1926 if (delay) {1927 if (!qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay,1928 poll->mask, poll->status)){1929 index = p_dev->ahw->reset.array_index;1930 addr = entry->dr_addr;1931 j = QLCRD32(p_dev, addr, &err);1932 if (err == -EIO)1933 return;1934 1935 p_dev->ahw->reset.array[index++] = j;1936 1937 if (index == QLC_83XX_MAX_RESET_SEQ_ENTRIES)1938 p_dev->ahw->reset.array_index = 1;1939 }1940 }1941 }1942}1943 1944static inline void qlcnic_83xx_seq_end(struct qlcnic_adapter *p_dev)1945{1946 p_dev->ahw->reset.seq_end = 1;1947}1948 1949static void qlcnic_83xx_template_end(struct qlcnic_adapter *p_dev)1950{1951 p_dev->ahw->reset.template_end = 1;1952 if (p_dev->ahw->reset.seq_error == 0)1953 dev_err(&p_dev->pdev->dev,1954 "HW restart process completed successfully.\n");1955 else1956 dev_err(&p_dev->pdev->dev,1957 "HW restart completed with timeout errors.\n");1958}1959 1960/**1961* qlcnic_83xx_exec_template_cmd1962*1963* @p_dev: adapter structure1964* @p_buff: Poiter to instruction template1965*1966* Template provides instructions to stop, restart and initalize firmware.1967* These instructions are abstracted as a series of read, write and1968* poll operations on hardware registers. Register information and operation1969* specifics are not exposed to the driver. Driver reads the template from1970* flash and executes the instructions located at pre-defined offsets.1971*1972* Returns: None1973* */1974static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,1975 char *p_buff)1976{1977 int index, entries;1978 struct qlc_83xx_entry_hdr *p_hdr;1979 char *entry = p_buff;1980 1981 p_dev->ahw->reset.seq_end = 0;1982 p_dev->ahw->reset.template_end = 0;1983 entries = p_dev->ahw->reset.hdr->entries;1984 index = p_dev->ahw->reset.seq_index;1985 1986 for (; (!p_dev->ahw->reset.seq_end) && (index < entries); index++) {1987 p_hdr = (struct qlc_83xx_entry_hdr *)entry;1988 1989 switch (p_hdr->cmd) {1990 case QLC_83XX_OPCODE_NOP:1991 break;1992 case QLC_83XX_OPCODE_WRITE_LIST:1993 qlcnic_83xx_write_list(p_dev, p_hdr);1994 break;1995 case QLC_83XX_OPCODE_READ_WRITE_LIST:1996 qlcnic_83xx_read_write_list(p_dev, p_hdr);1997 break;1998 case QLC_83XX_OPCODE_POLL_LIST:1999 qlcnic_83xx_poll_list(p_dev, p_hdr);2000 break;2001 case QLC_83XX_OPCODE_POLL_WRITE_LIST:2002 qlcnic_83xx_poll_write_list(p_dev, p_hdr);2003 break;2004 case QLC_83XX_OPCODE_READ_MODIFY_WRITE:2005 qlcnic_83xx_read_modify_write(p_dev, p_hdr);2006 break;2007 case QLC_83XX_OPCODE_SEQ_PAUSE:2008 qlcnic_83xx_pause(p_hdr);2009 break;2010 case QLC_83XX_OPCODE_SEQ_END:2011 qlcnic_83xx_seq_end(p_dev);2012 break;2013 case QLC_83XX_OPCODE_TMPL_END:2014 qlcnic_83xx_template_end(p_dev);2015 break;2016 case QLC_83XX_OPCODE_POLL_READ_LIST:2017 qlcnic_83xx_poll_read_list(p_dev, p_hdr);2018 break;2019 default:2020 dev_err(&p_dev->pdev->dev,2021 "%s: Unknown opcode 0x%04x in template %d\n",2022 __func__, p_hdr->cmd, index);2023 break;2024 }2025 entry += p_hdr->size;2026 cond_resched();2027 }2028 p_dev->ahw->reset.seq_index = index;2029}2030 2031static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)2032{2033 p_dev->ahw->reset.seq_index = 0;2034 2035 qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.stop_offset);2036 if (p_dev->ahw->reset.seq_end != 1)2037 dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2038}2039 2040static void qlcnic_83xx_start_hw(struct qlcnic_adapter *p_dev)2041{2042 qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.start_offset);2043 if (p_dev->ahw->reset.template_end != 1)2044 dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2045}2046 2047static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)2048{2049 qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.init_offset);2050 if (p_dev->ahw->reset.seq_end != 1)2051 dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);2052}2053 2054/* POST FW related definations*/2055#define QLC_83XX_POST_SIGNATURE_REG 0x416020142056#define QLC_83XX_POST_MODE_REG 0x416020182057#define QLC_83XX_POST_FAST_MODE 02058#define QLC_83XX_POST_MEDIUM_MODE 12059#define QLC_83XX_POST_SLOW_MODE 22060 2061/* POST Timeout values in milliseconds */2062#define QLC_83XX_POST_FAST_MODE_TIMEOUT 6902063#define QLC_83XX_POST_MED_MODE_TIMEOUT 29302064#define QLC_83XX_POST_SLOW_MODE_TIMEOUT 75002065 2066/* POST result values */2067#define QLC_83XX_POST_PASS 0xfffffff02068#define QLC_83XX_POST_ASIC_STRESS_TEST_FAIL 0xffffffff2069#define QLC_83XX_POST_DDR_TEST_FAIL 0xfffffffe2070#define QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL 0xfffffffc2071#define QLC_83XX_POST_FLASH_TEST_FAIL 0xfffffff82072 2073static int qlcnic_83xx_run_post(struct qlcnic_adapter *adapter)2074{2075 struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;2076 struct device *dev = &adapter->pdev->dev;2077 int timeout, count, ret = 0;2078 u32 signature;2079 2080 /* Set timeout values with extra 2 seconds of buffer */2081 switch (adapter->ahw->post_mode) {2082 case QLC_83XX_POST_FAST_MODE:2083 timeout = QLC_83XX_POST_FAST_MODE_TIMEOUT + 2000;2084 break;2085 case QLC_83XX_POST_MEDIUM_MODE:2086 timeout = QLC_83XX_POST_MED_MODE_TIMEOUT + 2000;2087 break;2088 case QLC_83XX_POST_SLOW_MODE:2089 timeout = QLC_83XX_POST_SLOW_MODE_TIMEOUT + 2000;2090 break;2091 default:2092 return -EINVAL;2093 }2094 2095 strscpy(fw_info->fw_file_name, QLC_83XX_POST_FW_FILE_NAME,2096 sizeof(fw_info->fw_file_name));2097 2098 ret = request_firmware(&fw_info->fw, fw_info->fw_file_name, dev);2099 if (ret) {2100 dev_err(dev, "POST firmware can not be loaded, skipping POST\n");2101 return 0;2102 }2103 2104 ret = qlcnic_83xx_copy_fw_file(adapter);2105 if (ret)2106 return ret;2107 2108 /* clear QLC_83XX_POST_SIGNATURE_REG register */2109 qlcnic_ind_wr(adapter, QLC_83XX_POST_SIGNATURE_REG, 0);2110 2111 /* Set POST mode */2112 qlcnic_ind_wr(adapter, QLC_83XX_POST_MODE_REG,2113 adapter->ahw->post_mode);2114 2115 QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2116 QLC_83XX_BOOT_FROM_FILE);2117 2118 qlcnic_83xx_start_hw(adapter);2119 2120 count = 0;2121 do {2122 msleep(100);2123 count += 100;2124 2125 signature = qlcnic_ind_rd(adapter, QLC_83XX_POST_SIGNATURE_REG);2126 if (signature == QLC_83XX_POST_PASS)2127 break;2128 } while (timeout > count);2129 2130 if (timeout <= count) {2131 dev_err(dev, "POST timed out, signature = 0x%08x\n", signature);2132 return -EIO;2133 }2134 2135 switch (signature) {2136 case QLC_83XX_POST_PASS:2137 dev_info(dev, "POST passed, Signature = 0x%08x\n", signature);2138 break;2139 case QLC_83XX_POST_ASIC_STRESS_TEST_FAIL:2140 dev_err(dev, "POST failed, Test case : ASIC STRESS TEST, Signature = 0x%08x\n",2141 signature);2142 ret = -EIO;2143 break;2144 case QLC_83XX_POST_DDR_TEST_FAIL:2145 dev_err(dev, "POST failed, Test case : DDT TEST, Signature = 0x%08x\n",2146 signature);2147 ret = -EIO;2148 break;2149 case QLC_83XX_POST_ASIC_MEMORY_TEST_FAIL:2150 dev_err(dev, "POST failed, Test case : ASIC MEMORY TEST, Signature = 0x%08x\n",2151 signature);2152 ret = -EIO;2153 break;2154 case QLC_83XX_POST_FLASH_TEST_FAIL:2155 dev_err(dev, "POST failed, Test case : FLASH TEST, Signature = 0x%08x\n",2156 signature);2157 ret = -EIO;2158 break;2159 default:2160 dev_err(dev, "POST failed, Test case : INVALID, Signature = 0x%08x\n",2161 signature);2162 ret = -EIO;2163 break;2164 }2165 2166 return ret;2167}2168 2169static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter)2170{2171 struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;2172 int err = -EIO;2173 2174 if (request_firmware(&fw_info->fw, fw_info->fw_file_name,2175 &(adapter->pdev->dev))) {2176 dev_err(&adapter->pdev->dev,2177 "No file FW image, loading flash FW image.\n");2178 QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2179 QLC_83XX_BOOT_FROM_FLASH);2180 } else {2181 if (qlcnic_83xx_copy_fw_file(adapter))2182 return err;2183 QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2184 QLC_83XX_BOOT_FROM_FILE);2185 }2186 2187 return 0;2188}2189 2190static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)2191{2192 u32 val;2193 int err = -EIO;2194 2195 qlcnic_83xx_stop_hw(adapter);2196 2197 /* Collect FW register dump if required */2198 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);2199 if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))2200 qlcnic_dump_fw(adapter);2201 2202 if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {2203 netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",2204 __func__);2205 qlcnic_83xx_idc_enter_failed_state(adapter, 1);2206 return err;2207 }2208 2209 qlcnic_83xx_init_hw(adapter);2210 2211 if (qlcnic_83xx_copy_bootloader(adapter))2212 return err;2213 2214 /* Check if POST needs to be run */2215 if (adapter->ahw->run_post) {2216 err = qlcnic_83xx_run_post(adapter);2217 if (err)2218 return err;2219 2220 /* No need to run POST in next reset sequence */2221 adapter->ahw->run_post = false;2222 2223 /* Again reset the adapter to load regular firmware */2224 qlcnic_83xx_stop_hw(adapter);2225 qlcnic_83xx_init_hw(adapter);2226 2227 err = qlcnic_83xx_copy_bootloader(adapter);2228 if (err)2229 return err;2230 }2231 2232 /* Boot either flash image or firmware image from host file system */2233 if (qlcnic_load_fw_file == 1) {2234 err = qlcnic_83xx_load_fw_image_from_host(adapter);2235 if (err)2236 return err;2237 } else {2238 QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,2239 QLC_83XX_BOOT_FROM_FLASH);2240 }2241 2242 qlcnic_83xx_start_hw(adapter);2243 if (qlcnic_83xx_check_hw_status(adapter))2244 return -EIO;2245 2246 return 0;2247}2248 2249static int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)2250{2251 int err;2252 struct qlcnic_info nic_info;2253 struct qlcnic_hardware_context *ahw = adapter->ahw;2254 2255 memset(&nic_info, 0, sizeof(struct qlcnic_info));2256 err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);2257 if (err)2258 return -EIO;2259 2260 ahw->physical_port = (u8) nic_info.phys_port;2261 ahw->switch_mode = nic_info.switch_mode;2262 ahw->max_tx_ques = nic_info.max_tx_ques;2263 ahw->max_rx_ques = nic_info.max_rx_ques;2264 ahw->capabilities = nic_info.capabilities;2265 ahw->max_mac_filters = nic_info.max_mac_filters;2266 ahw->max_mtu = nic_info.max_mtu;2267 2268 /* eSwitch capability indicates vNIC mode.2269 * vNIC and SRIOV are mutually exclusive operational modes.2270 * If SR-IOV capability is detected, SR-IOV physical function2271 * will get initialized in default mode.2272 * SR-IOV virtual function initialization follows a2273 * different code path and opmode.2274 * SRIOV mode has precedence over vNIC mode.2275 */2276 if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))2277 return QLC_83XX_DEFAULT_OPMODE;2278 2279 if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)2280 return QLCNIC_VNIC_MODE;2281 2282 return QLC_83XX_DEFAULT_OPMODE;2283}2284 2285int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)2286{2287 struct qlcnic_hardware_context *ahw = adapter->ahw;2288 u16 max_sds_rings, max_tx_rings;2289 int ret;2290 2291 ret = qlcnic_83xx_get_nic_configuration(adapter);2292 if (ret == -EIO)2293 return -EIO;2294 2295 if (ret == QLCNIC_VNIC_MODE) {2296 ahw->nic_mode = QLCNIC_VNIC_MODE;2297 2298 if (qlcnic_83xx_config_vnic_opmode(adapter))2299 return -EIO;2300 2301 max_sds_rings = QLCNIC_MAX_VNIC_SDS_RINGS;2302 max_tx_rings = QLCNIC_MAX_VNIC_TX_RINGS;2303 } else if (ret == QLC_83XX_DEFAULT_OPMODE) {2304 ahw->nic_mode = QLCNIC_DEFAULT_MODE;2305 adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;2306 ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;2307 max_sds_rings = QLCNIC_MAX_SDS_RINGS;2308 max_tx_rings = QLCNIC_MAX_TX_RINGS;2309 } else {2310 dev_err(&adapter->pdev->dev, "%s: Invalid opmode %d\n",2311 __func__, ret);2312 return -EIO;2313 }2314 2315 adapter->max_sds_rings = min(ahw->max_rx_ques, max_sds_rings);2316 adapter->max_tx_rings = min(ahw->max_tx_ques, max_tx_rings);2317 2318 return 0;2319}2320 2321static void qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter *adapter)2322{2323 struct qlcnic_hardware_context *ahw = adapter->ahw;2324 2325 if (ahw->port_type == QLCNIC_XGBE) {2326 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;2327 adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;2328 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;2329 adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;2330 2331 } else if (ahw->port_type == QLCNIC_GBE) {2332 adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;2333 adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;2334 adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;2335 adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;2336 }2337 adapter->num_txd = MAX_CMD_DESCRIPTORS;2338 adapter->max_rds_rings = MAX_RDS_RINGS;2339}2340 2341static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter)2342{2343 int err = -EIO;2344 2345 qlcnic_83xx_get_minidump_template(adapter);2346 if (qlcnic_83xx_get_port_info(adapter))2347 return err;2348 2349 qlcnic_83xx_config_buff_descriptors(adapter);2350 adapter->ahw->msix_supported = !!qlcnic_use_msi_x;2351 adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;2352 2353 dev_info(&adapter->pdev->dev, "HAL Version: %d\n",2354 adapter->ahw->fw_hal_version);2355 2356 return 0;2357}2358 2359#define IS_QLC_83XX_USED(a, b, c) (((1 << a->portnum) & b) || ((c >> 6) & 0x1))2360static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)2361{2362 struct qlcnic_cmd_args cmd;2363 u32 presence_mask, audit_mask;2364 int status;2365 2366 presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE);2367 audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);2368 2369 if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) {2370 status = qlcnic_alloc_mbx_args(&cmd, adapter,2371 QLCNIC_CMD_STOP_NIC_FUNC);2372 if (status)2373 return;2374 2375 cmd.req.arg[1] = BIT_31;2376 status = qlcnic_issue_cmd(adapter, &cmd);2377 if (status)2378 dev_err(&adapter->pdev->dev,2379 "Failed to clean up the function resources\n");2380 qlcnic_free_mbx_args(&cmd);2381 }2382}2383 2384static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)2385{2386 struct qlcnic_hardware_context *ahw = adapter->ahw;2387 struct pci_dev *pdev = adapter->pdev;2388 struct qlc_83xx_fw_info *fw_info;2389 int err = 0;2390 2391 ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL);2392 if (!ahw->fw_info) {2393 err = -ENOMEM;2394 } else {2395 fw_info = ahw->fw_info;2396 switch (pdev->device) {2397 case PCI_DEVICE_ID_QLOGIC_QLE834X:2398 case PCI_DEVICE_ID_QLOGIC_QLE8830:2399 strscpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME,2400 sizeof(fw_info->fw_file_name));2401 break;2402 case PCI_DEVICE_ID_QLOGIC_QLE844X:2403 strscpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME,2404 sizeof(fw_info->fw_file_name));2405 break;2406 default:2407 dev_err(&pdev->dev, "%s: Invalid device id\n",2408 __func__);2409 err = -EINVAL;2410 break;2411 }2412 }2413 2414 return err;2415}2416 2417static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter)2418{2419 u8 rx_cnt = QLCNIC_DEF_SDS_RINGS;2420 u8 tx_cnt = QLCNIC_DEF_TX_RINGS;2421 2422 adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;2423 adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;2424 2425 if (!adapter->ahw->msix_supported) {2426 rx_cnt = QLCNIC_SINGLE_RING;2427 tx_cnt = QLCNIC_SINGLE_RING;2428 }2429 2430 /* compute and set drv sds rings */2431 qlcnic_set_tx_ring_count(adapter, tx_cnt);2432 qlcnic_set_sds_ring_count(adapter, rx_cnt);2433}2434 2435int qlcnic_83xx_init(struct qlcnic_adapter *adapter)2436{2437 struct qlcnic_hardware_context *ahw = adapter->ahw;2438 int err = 0;2439 2440 adapter->rx_mac_learn = false;2441 ahw->msix_supported = !!qlcnic_use_msi_x;2442 2443 /* Check if POST needs to be run */2444 switch (qlcnic_load_fw_file) {2445 case 2:2446 ahw->post_mode = QLC_83XX_POST_FAST_MODE;2447 ahw->run_post = true;2448 break;2449 case 3:2450 ahw->post_mode = QLC_83XX_POST_MEDIUM_MODE;2451 ahw->run_post = true;2452 break;2453 case 4:2454 ahw->post_mode = QLC_83XX_POST_SLOW_MODE;2455 ahw->run_post = true;2456 break;2457 default:2458 ahw->run_post = false;2459 break;2460 }2461 2462 qlcnic_83xx_init_rings(adapter);2463 2464 err = qlcnic_83xx_init_mailbox_work(adapter);2465 if (err)2466 goto exit;2467 2468 if (qlcnic_sriov_vf_check(adapter)) {2469 err = qlcnic_sriov_vf_init(adapter);2470 if (err)2471 goto detach_mbx;2472 else2473 return err;2474 }2475 2476 if (qlcnic_83xx_read_flash_descriptor_table(adapter) ||2477 qlcnic_83xx_read_flash_mfg_id(adapter)) {2478 dev_err(&adapter->pdev->dev, "Failed reading flash mfg id\n");2479 err = -ENOTRECOVERABLE;2480 goto detach_mbx;2481 }2482 2483 err = qlcnic_83xx_check_hw_status(adapter);2484 if (err)2485 goto detach_mbx;2486 2487 err = qlcnic_83xx_get_fw_info(adapter);2488 if (err)2489 goto detach_mbx;2490 2491 err = qlcnic_83xx_idc_init(adapter);2492 if (err)2493 goto detach_mbx;2494 2495 err = qlcnic_setup_intr(adapter);2496 if (err) {2497 dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");2498 goto disable_intr;2499 }2500 2501 INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);2502 2503 err = qlcnic_83xx_setup_mbx_intr(adapter);2504 if (err)2505 goto disable_mbx_intr;2506 2507 qlcnic_83xx_clear_function_resources(adapter);2508 2509 err = qlcnic_dcb_enable(adapter->dcb);2510 if (err) {2511 qlcnic_dcb_free(adapter->dcb);2512 goto disable_mbx_intr;2513 }2514 2515 qlcnic_83xx_initialize_nic(adapter, 1);2516 qlcnic_dcb_get_info(adapter->dcb);2517 2518 /* Configure default, SR-IOV or Virtual NIC mode of operation */2519 err = qlcnic_83xx_configure_opmode(adapter);2520 if (err)2521 goto disable_mbx_intr;2522 2523 2524 /* Perform operating mode specific initialization */2525 err = adapter->nic_ops->init_driver(adapter);2526 if (err)2527 goto disable_mbx_intr;2528 2529 /* Periodically monitor device status */2530 qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);2531 return 0;2532 2533disable_mbx_intr:2534 qlcnic_83xx_free_mbx_intr(adapter);2535 2536disable_intr:2537 qlcnic_teardown_intr(adapter);2538 2539detach_mbx:2540 qlcnic_83xx_detach_mailbox_work(adapter);2541 qlcnic_83xx_free_mailbox(ahw->mailbox);2542 ahw->mailbox = NULL;2543exit:2544 return err;2545}2546 2547void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)2548{2549 struct qlcnic_hardware_context *ahw = adapter->ahw;2550 struct qlc_83xx_idc *idc = &ahw->idc;2551 2552 clear_bit(QLC_83XX_MBX_READY, &idc->status);2553 cancel_delayed_work_sync(&adapter->fw_work);2554 2555 if (ahw->nic_mode == QLCNIC_VNIC_MODE)2556 qlcnic_83xx_disable_vnic_mode(adapter, 1);2557 2558 qlcnic_83xx_idc_detach_driver(adapter);2559 qlcnic_83xx_initialize_nic(adapter, 0);2560 2561 cancel_delayed_work_sync(&adapter->idc_aen_work);2562}2563 2564int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter)2565{2566 struct qlcnic_hardware_context *ahw = adapter->ahw;2567 struct qlc_83xx_idc *idc = &ahw->idc;2568 int ret = 0;2569 u32 owner;2570 2571 /* Mark the previous IDC state as NEED_RESET so2572 * that state_entry() will perform the reattachment2573 * and bringup the device2574 */2575 idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET;2576 owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);2577 if (ahw->pci_func == owner) {2578 ret = qlcnic_83xx_restart_hw(adapter);2579 if (ret < 0)2580 return ret;2581 qlcnic_83xx_idc_clear_registers(adapter, 0);2582 }2583 2584 ret = idc->state_entry(adapter);2585 return ret;2586}2587 2588void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter)2589{2590 struct qlcnic_hardware_context *ahw = adapter->ahw;2591 struct qlc_83xx_idc *idc = &ahw->idc;2592 u32 owner;2593 2594 idc->prev_state = QLC_83XX_IDC_DEV_READY;2595 owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);2596 if (ahw->pci_func == owner)2597 qlcnic_83xx_idc_enter_ready_state(adapter, 0);2598 2599 qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0);2600}2601