1585 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic iSCSI HBA Driver4 * Copyright (c) 2003-2013 QLogic Corporation5 */6 7#include <linux/ratelimit.h>8 9#include "ql4_def.h"10#include "ql4_version.h"11#include "ql4_glbl.h"12#include "ql4_dbg.h"13#include "ql4_inline.h"14 15uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr)16{17 return readl((void __iomem *)(ha->nx_pcibase + addr));18}19 20void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val)21{22 writel(val, (void __iomem *)(ha->nx_pcibase + addr));23}24 25static int qla4_83xx_set_win_base(struct scsi_qla_host *ha, uint32_t addr)26{27 uint32_t val;28 int ret_val = QLA_SUCCESS;29 30 qla4_83xx_wr_reg(ha, QLA83XX_CRB_WIN_FUNC(ha->func_num), addr);31 val = qla4_83xx_rd_reg(ha, QLA83XX_CRB_WIN_FUNC(ha->func_num));32 if (val != addr) {33 ql4_printk(KERN_ERR, ha, "%s: Failed to set register window : addr written 0x%x, read 0x%x!\n",34 __func__, addr, val);35 ret_val = QLA_ERROR;36 }37 38 return ret_val;39}40 41int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,42 uint32_t *data)43{44 int ret_val;45 46 ret_val = qla4_83xx_set_win_base(ha, addr);47 48 if (ret_val == QLA_SUCCESS) {49 *data = qla4_83xx_rd_reg(ha, QLA83XX_WILDCARD);50 } else {51 *data = 0xffffffff;52 ql4_printk(KERN_ERR, ha, "%s: failed read of addr 0x%x!\n",53 __func__, addr);54 }55 56 return ret_val;57}58 59int qla4_83xx_wr_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,60 uint32_t data)61{62 int ret_val;63 64 ret_val = qla4_83xx_set_win_base(ha, addr);65 66 if (ret_val == QLA_SUCCESS)67 qla4_83xx_wr_reg(ha, QLA83XX_WILDCARD, data);68 else69 ql4_printk(KERN_ERR, ha, "%s: failed wrt to addr 0x%x, data 0x%x\n",70 __func__, addr, data);71 72 return ret_val;73}74 75static int qla4_83xx_flash_lock(struct scsi_qla_host *ha)76{77 int lock_owner;78 int timeout = 0;79 uint32_t lock_status = 0;80 int ret_val = QLA_SUCCESS;81 82 while (lock_status == 0) {83 lock_status = qla4_83xx_rd_reg(ha, QLA83XX_FLASH_LOCK);84 if (lock_status)85 break;86 87 if (++timeout >= QLA83XX_FLASH_LOCK_TIMEOUT / 20) {88 lock_owner = qla4_83xx_rd_reg(ha,89 QLA83XX_FLASH_LOCK_ID);90 ql4_printk(KERN_ERR, ha, "%s: flash lock by func %d failed, held by func %d\n",91 __func__, ha->func_num, lock_owner);92 ret_val = QLA_ERROR;93 break;94 }95 msleep(20);96 }97 98 qla4_83xx_wr_reg(ha, QLA83XX_FLASH_LOCK_ID, ha->func_num);99 return ret_val;100}101 102static void qla4_83xx_flash_unlock(struct scsi_qla_host *ha)103{104 /* Reading FLASH_UNLOCK register unlocks the Flash */105 qla4_83xx_wr_reg(ha, QLA83XX_FLASH_LOCK_ID, 0xFF);106 qla4_83xx_rd_reg(ha, QLA83XX_FLASH_UNLOCK);107}108 109int qla4_83xx_flash_read_u32(struct scsi_qla_host *ha, uint32_t flash_addr,110 uint8_t *p_data, int u32_word_count)111{112 int i;113 uint32_t u32_word;114 uint32_t addr = flash_addr;115 int ret_val = QLA_SUCCESS;116 117 ret_val = qla4_83xx_flash_lock(ha);118 if (ret_val == QLA_ERROR)119 goto exit_lock_error;120 121 if (addr & 0x03) {122 ql4_printk(KERN_ERR, ha, "%s: Illegal addr = 0x%x\n",123 __func__, addr);124 ret_val = QLA_ERROR;125 goto exit_flash_read;126 }127 128 for (i = 0; i < u32_word_count; i++) {129 ret_val = qla4_83xx_wr_reg_indirect(ha,130 QLA83XX_FLASH_DIRECT_WINDOW,131 (addr & 0xFFFF0000));132 if (ret_val == QLA_ERROR) {133 ql4_printk(KERN_ERR, ha, "%s: failed to write addr 0x%x to FLASH_DIRECT_WINDOW\n!",134 __func__, addr);135 goto exit_flash_read;136 }137 138 ret_val = qla4_83xx_rd_reg_indirect(ha,139 QLA83XX_FLASH_DIRECT_DATA(addr),140 &u32_word);141 if (ret_val == QLA_ERROR) {142 ql4_printk(KERN_ERR, ha, "%s: failed to read addr 0x%x!\n",143 __func__, addr);144 goto exit_flash_read;145 }146 147 *(__le32 *)p_data = le32_to_cpu(u32_word);148 p_data = p_data + 4;149 addr = addr + 4;150 }151 152exit_flash_read:153 qla4_83xx_flash_unlock(ha);154 155exit_lock_error:156 return ret_val;157}158 159int qla4_83xx_lockless_flash_read_u32(struct scsi_qla_host *ha,160 uint32_t flash_addr, uint8_t *p_data,161 int u32_word_count)162{163 uint32_t i;164 uint32_t u32_word;165 uint32_t flash_offset;166 uint32_t addr = flash_addr;167 int ret_val = QLA_SUCCESS;168 169 flash_offset = addr & (QLA83XX_FLASH_SECTOR_SIZE - 1);170 171 if (addr & 0x3) {172 ql4_printk(KERN_ERR, ha, "%s: Illegal addr = 0x%x\n",173 __func__, addr);174 ret_val = QLA_ERROR;175 goto exit_lockless_read;176 }177 178 ret_val = qla4_83xx_wr_reg_indirect(ha, QLA83XX_FLASH_DIRECT_WINDOW,179 addr);180 if (ret_val == QLA_ERROR) {181 ql4_printk(KERN_ERR, ha, "%s: failed to write addr 0x%x to FLASH_DIRECT_WINDOW!\n",182 __func__, addr);183 goto exit_lockless_read;184 }185 186 /* Check if data is spread across multiple sectors */187 if ((flash_offset + (u32_word_count * sizeof(uint32_t))) >188 (QLA83XX_FLASH_SECTOR_SIZE - 1)) {189 190 /* Multi sector read */191 for (i = 0; i < u32_word_count; i++) {192 ret_val = qla4_83xx_rd_reg_indirect(ha,193 QLA83XX_FLASH_DIRECT_DATA(addr),194 &u32_word);195 if (ret_val == QLA_ERROR) {196 ql4_printk(KERN_ERR, ha, "%s: failed to read addr 0x%x!\n",197 __func__, addr);198 goto exit_lockless_read;199 }200 201 *(__le32 *)p_data = le32_to_cpu(u32_word);202 p_data = p_data + 4;203 addr = addr + 4;204 flash_offset = flash_offset + 4;205 206 if (flash_offset > (QLA83XX_FLASH_SECTOR_SIZE - 1)) {207 /* This write is needed once for each sector */208 ret_val = qla4_83xx_wr_reg_indirect(ha,209 QLA83XX_FLASH_DIRECT_WINDOW,210 addr);211 if (ret_val == QLA_ERROR) {212 ql4_printk(KERN_ERR, ha, "%s: failed to write addr 0x%x to FLASH_DIRECT_WINDOW!\n",213 __func__, addr);214 goto exit_lockless_read;215 }216 flash_offset = 0;217 }218 }219 } else {220 /* Single sector read */221 for (i = 0; i < u32_word_count; i++) {222 ret_val = qla4_83xx_rd_reg_indirect(ha,223 QLA83XX_FLASH_DIRECT_DATA(addr),224 &u32_word);225 if (ret_val == QLA_ERROR) {226 ql4_printk(KERN_ERR, ha, "%s: failed to read addr 0x%x!\n",227 __func__, addr);228 goto exit_lockless_read;229 }230 231 *(__le32 *)p_data = le32_to_cpu(u32_word);232 p_data = p_data + 4;233 addr = addr + 4;234 }235 }236 237exit_lockless_read:238 return ret_val;239}240 241void qla4_83xx_rom_lock_recovery(struct scsi_qla_host *ha)242{243 if (qla4_83xx_flash_lock(ha))244 ql4_printk(KERN_INFO, ha, "%s: Resetting rom lock\n", __func__);245 246 /*247 * We got the lock, or someone else is holding the lock248 * since we are restting, forcefully unlock249 */250 qla4_83xx_flash_unlock(ha);251}252 253#define INTENT_TO_RECOVER 0x01254#define PROCEED_TO_RECOVER 0x02255 256static int qla4_83xx_lock_recovery(struct scsi_qla_host *ha)257{258 259 uint32_t lock = 0, lockid;260 int ret_val = QLA_ERROR;261 262 lockid = ha->isp_ops->rd_reg_direct(ha, QLA83XX_DRV_LOCKRECOVERY);263 264 /* Check for other Recovery in progress, go wait */265 if ((lockid & 0x3) != 0)266 goto exit_lock_recovery;267 268 /* Intent to Recover */269 ha->isp_ops->wr_reg_direct(ha, QLA83XX_DRV_LOCKRECOVERY,270 (ha->func_num << 2) | INTENT_TO_RECOVER);271 272 msleep(200);273 274 /* Check Intent to Recover is advertised */275 lockid = ha->isp_ops->rd_reg_direct(ha, QLA83XX_DRV_LOCKRECOVERY);276 if ((lockid & 0x3C) != (ha->func_num << 2))277 goto exit_lock_recovery;278 279 ql4_printk(KERN_INFO, ha, "%s: IDC Lock recovery initiated for func %d\n",280 __func__, ha->func_num);281 282 /* Proceed to Recover */283 ha->isp_ops->wr_reg_direct(ha, QLA83XX_DRV_LOCKRECOVERY,284 (ha->func_num << 2) | PROCEED_TO_RECOVER);285 286 /* Force Unlock */287 ha->isp_ops->wr_reg_direct(ha, QLA83XX_DRV_LOCK_ID, 0xFF);288 ha->isp_ops->rd_reg_direct(ha, QLA83XX_DRV_UNLOCK);289 290 /* Clear bits 0-5 in IDC_RECOVERY register*/291 ha->isp_ops->wr_reg_direct(ha, QLA83XX_DRV_LOCKRECOVERY, 0);292 293 /* Get lock */294 lock = ha->isp_ops->rd_reg_direct(ha, QLA83XX_DRV_LOCK);295 if (lock) {296 lockid = ha->isp_ops->rd_reg_direct(ha, QLA83XX_DRV_LOCK_ID);297 lockid = ((lockid + (1 << 8)) & ~0xFF) | ha->func_num;298 ha->isp_ops->wr_reg_direct(ha, QLA83XX_DRV_LOCK_ID, lockid);299 ret_val = QLA_SUCCESS;300 }301 302exit_lock_recovery:303 return ret_val;304}305 306#define QLA83XX_DRV_LOCK_MSLEEP 200307 308int qla4_83xx_drv_lock(struct scsi_qla_host *ha)309{310 int timeout = 0;311 uint32_t status = 0;312 int ret_val = QLA_SUCCESS;313 uint32_t first_owner = 0;314 uint32_t tmo_owner = 0;315 uint32_t lock_id;316 uint32_t func_num;317 uint32_t lock_cnt;318 319 while (status == 0) {320 status = qla4_83xx_rd_reg(ha, QLA83XX_DRV_LOCK);321 if (status) {322 /* Increment Counter (8-31) and update func_num (0-7) on323 * getting a successful lock */324 lock_id = qla4_83xx_rd_reg(ha, QLA83XX_DRV_LOCK_ID);325 lock_id = ((lock_id + (1 << 8)) & ~0xFF) | ha->func_num;326 qla4_83xx_wr_reg(ha, QLA83XX_DRV_LOCK_ID, lock_id);327 break;328 }329 330 if (timeout == 0)331 /* Save counter + ID of function holding the lock for332 * first failure */333 first_owner = ha->isp_ops->rd_reg_direct(ha,334 QLA83XX_DRV_LOCK_ID);335 336 if (++timeout >=337 (QLA83XX_DRV_LOCK_TIMEOUT / QLA83XX_DRV_LOCK_MSLEEP)) {338 tmo_owner = qla4_83xx_rd_reg(ha, QLA83XX_DRV_LOCK_ID);339 func_num = tmo_owner & 0xFF;340 lock_cnt = tmo_owner >> 8;341 ql4_printk(KERN_INFO, ha, "%s: Lock by func %d failed after 2s, lock held by func %d, lock count %d, first_owner %d\n",342 __func__, ha->func_num, func_num, lock_cnt,343 (first_owner & 0xFF));344 345 if (first_owner != tmo_owner) {346 /* Some other driver got lock, OR same driver347 * got lock again (counter value changed), when348 * we were waiting for lock.349 * Retry for another 2 sec */350 ql4_printk(KERN_INFO, ha, "%s: IDC lock failed for func %d\n",351 __func__, ha->func_num);352 timeout = 0;353 } else {354 /* Same driver holding lock > 2sec.355 * Force Recovery */356 ret_val = qla4_83xx_lock_recovery(ha);357 if (ret_val == QLA_SUCCESS) {358 /* Recovered and got lock */359 ql4_printk(KERN_INFO, ha, "%s: IDC lock Recovery by %d successful\n",360 __func__, ha->func_num);361 break;362 }363 /* Recovery Failed, some other function364 * has the lock, wait for 2secs and retry */365 ql4_printk(KERN_INFO, ha, "%s: IDC lock Recovery by %d failed, Retrying timeout\n",366 __func__, ha->func_num);367 timeout = 0;368 }369 }370 msleep(QLA83XX_DRV_LOCK_MSLEEP);371 }372 373 return ret_val;374}375 376void qla4_83xx_drv_unlock(struct scsi_qla_host *ha)377{378 int id;379 380 id = qla4_83xx_rd_reg(ha, QLA83XX_DRV_LOCK_ID);381 382 if ((id & 0xFF) != ha->func_num) {383 ql4_printk(KERN_ERR, ha, "%s: IDC Unlock by %d failed, lock owner is %d\n",384 __func__, ha->func_num, (id & 0xFF));385 return;386 }387 388 /* Keep lock counter value, update the ha->func_num to 0xFF */389 qla4_83xx_wr_reg(ha, QLA83XX_DRV_LOCK_ID, (id | 0xFF));390 qla4_83xx_rd_reg(ha, QLA83XX_DRV_UNLOCK);391}392 393void qla4_83xx_set_idc_dontreset(struct scsi_qla_host *ha)394{395 uint32_t idc_ctrl;396 397 idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);398 idc_ctrl |= DONTRESET_BIT0;399 qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL, idc_ctrl);400 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: idc_ctrl = %d\n", __func__,401 idc_ctrl));402}403 404void qla4_83xx_clear_idc_dontreset(struct scsi_qla_host *ha)405{406 uint32_t idc_ctrl;407 408 idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);409 idc_ctrl &= ~DONTRESET_BIT0;410 qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL, idc_ctrl);411 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: idc_ctrl = %d\n", __func__,412 idc_ctrl));413}414 415int qla4_83xx_idc_dontreset(struct scsi_qla_host *ha)416{417 uint32_t idc_ctrl;418 419 idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);420 return idc_ctrl & DONTRESET_BIT0;421}422 423/*-------------------------IDC State Machine ---------------------*/424 425enum {426 UNKNOWN_CLASS = 0,427 NIC_CLASS,428 FCOE_CLASS,429 ISCSI_CLASS430};431 432struct device_info {433 int func_num;434 int device_type;435 int port_num;436};437 438int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha)439{440 uint32_t drv_active;441 uint32_t dev_part, dev_part1, dev_part2;442 int i;443 struct device_info device_map[16];444 int func_nibble;445 int nibble;446 int nic_present = 0;447 int iscsi_present = 0;448 int iscsi_func_low = 0;449 450 /* Use the dev_partition register to determine the PCI function number451 * and then check drv_active register to see which driver is loaded */452 dev_part1 = qla4_83xx_rd_reg(ha,453 ha->reg_tbl[QLA8XXX_CRB_DEV_PART_INFO]);454 dev_part2 = qla4_83xx_rd_reg(ha, QLA83XX_CRB_DEV_PART_INFO2);455 drv_active = qla4_83xx_rd_reg(ha, ha->reg_tbl[QLA8XXX_CRB_DRV_ACTIVE]);456 457 /* Each function has 4 bits in dev_partition Info register,458 * Lower 2 bits - device type, Upper 2 bits - physical port number */459 dev_part = dev_part1;460 for (i = nibble = 0; i <= 15; i++, nibble++) {461 func_nibble = dev_part & (0xF << (nibble * 4));462 func_nibble >>= (nibble * 4);463 device_map[i].func_num = i;464 device_map[i].device_type = func_nibble & 0x3;465 device_map[i].port_num = func_nibble & 0xC;466 467 if (device_map[i].device_type == NIC_CLASS) {468 if (drv_active & (1 << device_map[i].func_num)) {469 nic_present++;470 break;471 }472 } else if (device_map[i].device_type == ISCSI_CLASS) {473 if (drv_active & (1 << device_map[i].func_num)) {474 if (!iscsi_present ||475 iscsi_func_low > device_map[i].func_num)476 iscsi_func_low = device_map[i].func_num;477 478 iscsi_present++;479 }480 }481 482 /* For function_num[8..15] get info from dev_part2 register */483 if (nibble == 7) {484 nibble = 0;485 dev_part = dev_part2;486 }487 }488 489 /* NIC, iSCSI and FCOE are the Reset owners based on order, NIC gets490 * precedence over iSCSI and FCOE and iSCSI over FCOE, based on drivers491 * present. */492 if (!nic_present && (ha->func_num == iscsi_func_low)) {493 DEBUG2(ql4_printk(KERN_INFO, ha,494 "%s: can reset - NIC not present and lower iSCSI function is %d\n",495 __func__, ha->func_num));496 return 1;497 }498 499 return 0;500}501 502/**503 * qla4_83xx_need_reset_handler - Code to start reset sequence504 * @ha: pointer to adapter structure505 *506 * Note: IDC lock must be held upon entry507 **/508void qla4_83xx_need_reset_handler(struct scsi_qla_host *ha)509{510 uint32_t dev_state, drv_state, drv_active;511 unsigned long reset_timeout, dev_init_timeout;512 513 ql4_printk(KERN_INFO, ha, "%s: Performing ISP error recovery\n",514 __func__);515 516 if (!test_bit(AF_8XXX_RST_OWNER, &ha->flags)) {517 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: reset acknowledged\n",518 __func__));519 qla4_8xxx_set_rst_ready(ha);520 521 /* Non-reset owners ACK Reset and wait for device INIT state522 * as part of Reset Recovery by Reset Owner */523 dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);524 525 do {526 if (time_after_eq(jiffies, dev_init_timeout)) {527 ql4_printk(KERN_INFO, ha, "%s: Non Reset owner dev init timeout\n",528 __func__);529 break;530 }531 532 ha->isp_ops->idc_unlock(ha);533 msleep(1000);534 ha->isp_ops->idc_lock(ha);535 536 dev_state = qla4_8xxx_rd_direct(ha,537 QLA8XXX_CRB_DEV_STATE);538 } while (dev_state == QLA8XXX_DEV_NEED_RESET);539 } else {540 qla4_8xxx_set_rst_ready(ha);541 reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);542 drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);543 drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);544 545 ql4_printk(KERN_INFO, ha, "%s: drv_state = 0x%x, drv_active = 0x%x\n",546 __func__, drv_state, drv_active);547 548 while (drv_state != drv_active) {549 if (time_after_eq(jiffies, reset_timeout)) {550 ql4_printk(KERN_INFO, ha, "%s: %s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n",551 __func__, DRIVER_NAME, drv_state,552 drv_active);553 break;554 }555 556 ha->isp_ops->idc_unlock(ha);557 msleep(1000);558 ha->isp_ops->idc_lock(ha);559 560 drv_state = qla4_8xxx_rd_direct(ha,561 QLA8XXX_CRB_DRV_STATE);562 drv_active = qla4_8xxx_rd_direct(ha,563 QLA8XXX_CRB_DRV_ACTIVE);564 }565 566 if (drv_state != drv_active) {567 ql4_printk(KERN_INFO, ha, "%s: Reset_owner turning off drv_active of non-acking function 0x%x\n",568 __func__, (drv_active ^ drv_state));569 drv_active = drv_active & drv_state;570 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE,571 drv_active);572 }573 574 clear_bit(AF_8XXX_RST_OWNER, &ha->flags);575 /* Start Reset Recovery */576 qla4_8xxx_device_bootstrap(ha);577 }578}579 580void qla4_83xx_get_idc_param(struct scsi_qla_host *ha)581{582 uint32_t idc_params, ret_val;583 584 ret_val = qla4_83xx_flash_read_u32(ha, QLA83XX_IDC_PARAM_ADDR,585 (uint8_t *)&idc_params, 1);586 if (ret_val == QLA_SUCCESS) {587 ha->nx_dev_init_timeout = idc_params & 0xFFFF;588 ha->nx_reset_timeout = (idc_params >> 16) & 0xFFFF;589 } else {590 ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT;591 ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT;592 }593 594 DEBUG2(ql4_printk(KERN_DEBUG, ha,595 "%s: ha->nx_dev_init_timeout = %d, ha->nx_reset_timeout = %d\n",596 __func__, ha->nx_dev_init_timeout,597 ha->nx_reset_timeout));598}599 600/*-------------------------Reset Sequence Functions-----------------------*/601 602static void qla4_83xx_dump_reset_seq_hdr(struct scsi_qla_host *ha)603{604 uint8_t *phdr;605 606 if (!ha->reset_tmplt.buff) {607 ql4_printk(KERN_ERR, ha, "%s: Error: Invalid reset_seq_template\n",608 __func__);609 return;610 }611 612 phdr = ha->reset_tmplt.buff;613 614 DEBUG2(ql4_printk(KERN_INFO, ha,615 "Reset Template: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",616 *phdr, *(phdr+1), *(phdr+2), *(phdr+3), *(phdr+4),617 *(phdr+5), *(phdr+6), *(phdr+7), *(phdr + 8),618 *(phdr+9), *(phdr+10), *(phdr+11), *(phdr+12),619 *(phdr+13), *(phdr+14), *(phdr+15)));620}621 622static int qla4_83xx_copy_bootloader(struct scsi_qla_host *ha)623{624 uint8_t *p_cache;625 uint32_t src, count, size;626 uint64_t dest;627 int ret_val = QLA_SUCCESS;628 629 src = QLA83XX_BOOTLOADER_FLASH_ADDR;630 dest = qla4_83xx_rd_reg(ha, QLA83XX_BOOTLOADER_ADDR);631 size = qla4_83xx_rd_reg(ha, QLA83XX_BOOTLOADER_SIZE);632 633 /* 128 bit alignment check */634 if (size & 0xF)635 size = (size + 16) & ~0xF;636 637 /* 16 byte count */638 count = size/16;639 640 p_cache = vmalloc(size);641 if (p_cache == NULL) {642 ql4_printk(KERN_ERR, ha, "%s: Failed to allocate memory for boot loader cache\n",643 __func__);644 ret_val = QLA_ERROR;645 goto exit_copy_bootloader;646 }647 648 ret_val = qla4_83xx_lockless_flash_read_u32(ha, src, p_cache,649 size / sizeof(uint32_t));650 if (ret_val == QLA_ERROR) {651 ql4_printk(KERN_ERR, ha, "%s: Error reading firmware from flash\n",652 __func__);653 goto exit_copy_error;654 }655 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Read firmware from flash\n",656 __func__));657 658 /* 128 bit/16 byte write to MS memory */659 ret_val = qla4_8xxx_ms_mem_write_128b(ha, dest, (uint32_t *)p_cache,660 count);661 if (ret_val == QLA_ERROR) {662 ql4_printk(KERN_ERR, ha, "%s: Error writing firmware to MS\n",663 __func__);664 goto exit_copy_error;665 }666 667 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Wrote firmware size %d to MS\n",668 __func__, size));669 670exit_copy_error:671 vfree(p_cache);672 673exit_copy_bootloader:674 return ret_val;675}676 677static int qla4_83xx_check_cmd_peg_status(struct scsi_qla_host *ha)678{679 uint32_t val, ret_val = QLA_ERROR;680 int retries = CRB_CMDPEG_CHECK_RETRY_COUNT;681 682 do {683 val = qla4_83xx_rd_reg(ha, QLA83XX_CMDPEG_STATE);684 if (val == PHAN_INITIALIZE_COMPLETE) {685 DEBUG2(ql4_printk(KERN_INFO, ha,686 "%s: Command Peg initialization complete. State=0x%x\n",687 __func__, val));688 ret_val = QLA_SUCCESS;689 break;690 }691 msleep(CRB_CMDPEG_CHECK_DELAY);692 } while (--retries);693 694 return ret_val;695}696 697/**698 * qla4_83xx_poll_reg - Poll the given CRB addr for duration msecs till699 * value read ANDed with test_mask is equal to test_result.700 *701 * @ha : Pointer to adapter structure702 * @addr : CRB register address703 * @duration : Poll for total of "duration" msecs704 * @test_mask : Mask value read with "test_mask"705 * @test_result : Compare (value&test_mask) with test_result.706 **/707static int qla4_83xx_poll_reg(struct scsi_qla_host *ha, uint32_t addr,708 int duration, uint32_t test_mask,709 uint32_t test_result)710{711 uint32_t value;712 uint8_t retries;713 int ret_val = QLA_SUCCESS;714 715 ret_val = qla4_83xx_rd_reg_indirect(ha, addr, &value);716 if (ret_val == QLA_ERROR)717 goto exit_poll_reg;718 719 retries = duration / 10;720 do {721 if ((value & test_mask) != test_result) {722 msleep(duration / 10);723 ret_val = qla4_83xx_rd_reg_indirect(ha, addr, &value);724 if (ret_val == QLA_ERROR)725 goto exit_poll_reg;726 727 ret_val = QLA_ERROR;728 } else {729 ret_val = QLA_SUCCESS;730 break;731 }732 } while (retries--);733 734exit_poll_reg:735 if (ret_val == QLA_ERROR) {736 ha->reset_tmplt.seq_error++;737 ql4_printk(KERN_ERR, ha, "%s: Poll Failed: 0x%08x 0x%08x 0x%08x\n",738 __func__, value, test_mask, test_result);739 }740 741 return ret_val;742}743 744static int qla4_83xx_reset_seq_checksum_test(struct scsi_qla_host *ha)745{746 uint32_t sum = 0;747 uint16_t *buff = (uint16_t *)ha->reset_tmplt.buff;748 int u16_count = ha->reset_tmplt.hdr->size / sizeof(uint16_t);749 int ret_val;750 751 while (u16_count-- > 0)752 sum += *buff++;753 754 while (sum >> 16)755 sum = (sum & 0xFFFF) + (sum >> 16);756 757 /* checksum of 0 indicates a valid template */758 if (~sum) {759 ret_val = QLA_SUCCESS;760 } else {761 ql4_printk(KERN_ERR, ha, "%s: Reset seq checksum failed\n",762 __func__);763 ret_val = QLA_ERROR;764 }765 766 return ret_val;767}768 769/**770 * qla4_83xx_read_reset_template - Read Reset Template from Flash771 * @ha: Pointer to adapter structure772 **/773void qla4_83xx_read_reset_template(struct scsi_qla_host *ha)774{775 uint8_t *p_buff;776 uint32_t addr, tmplt_hdr_def_size, tmplt_hdr_size;777 uint32_t ret_val;778 779 ha->reset_tmplt.seq_error = 0;780 ha->reset_tmplt.buff = vmalloc(QLA83XX_RESTART_TEMPLATE_SIZE);781 if (ha->reset_tmplt.buff == NULL) {782 ql4_printk(KERN_ERR, ha, "%s: Failed to allocate reset template resources\n",783 __func__);784 goto exit_read_reset_template;785 }786 787 p_buff = ha->reset_tmplt.buff;788 addr = QLA83XX_RESET_TEMPLATE_ADDR;789 790 tmplt_hdr_def_size = sizeof(struct qla4_83xx_reset_template_hdr) /791 sizeof(uint32_t);792 793 DEBUG2(ql4_printk(KERN_INFO, ha,794 "%s: Read template hdr size %d from Flash\n",795 __func__, tmplt_hdr_def_size));796 797 /* Copy template header from flash */798 ret_val = qla4_83xx_flash_read_u32(ha, addr, p_buff,799 tmplt_hdr_def_size);800 if (ret_val != QLA_SUCCESS) {801 ql4_printk(KERN_ERR, ha, "%s: Failed to read reset template\n",802 __func__);803 goto exit_read_template_error;804 }805 806 ha->reset_tmplt.hdr =807 (struct qla4_83xx_reset_template_hdr *)ha->reset_tmplt.buff;808 809 /* Validate the template header size and signature */810 tmplt_hdr_size = ha->reset_tmplt.hdr->hdr_size/sizeof(uint32_t);811 if ((tmplt_hdr_size != tmplt_hdr_def_size) ||812 (ha->reset_tmplt.hdr->signature != RESET_TMPLT_HDR_SIGNATURE)) {813 ql4_printk(KERN_ERR, ha, "%s: Template Header size %d is invalid, tmplt_hdr_def_size %d\n",814 __func__, tmplt_hdr_size, tmplt_hdr_def_size);815 goto exit_read_template_error;816 }817 818 addr = QLA83XX_RESET_TEMPLATE_ADDR + ha->reset_tmplt.hdr->hdr_size;819 p_buff = ha->reset_tmplt.buff + ha->reset_tmplt.hdr->hdr_size;820 tmplt_hdr_def_size = (ha->reset_tmplt.hdr->size -821 ha->reset_tmplt.hdr->hdr_size) / sizeof(uint32_t);822 823 DEBUG2(ql4_printk(KERN_INFO, ha,824 "%s: Read rest of the template size %d\n",825 __func__, ha->reset_tmplt.hdr->size));826 827 /* Copy rest of the template */828 ret_val = qla4_83xx_flash_read_u32(ha, addr, p_buff,829 tmplt_hdr_def_size);830 if (ret_val != QLA_SUCCESS) {831 ql4_printk(KERN_ERR, ha, "%s: Failed to read reset template\n",832 __func__);833 goto exit_read_template_error;834 }835 836 /* Integrity check */837 if (qla4_83xx_reset_seq_checksum_test(ha)) {838 ql4_printk(KERN_ERR, ha, "%s: Reset Seq checksum failed!\n",839 __func__);840 goto exit_read_template_error;841 }842 DEBUG2(ql4_printk(KERN_INFO, ha,843 "%s: Reset Seq checksum passed, Get stop, start and init seq offsets\n",844 __func__));845 846 /* Get STOP, START, INIT sequence offsets */847 ha->reset_tmplt.init_offset = ha->reset_tmplt.buff +848 ha->reset_tmplt.hdr->init_seq_offset;849 ha->reset_tmplt.start_offset = ha->reset_tmplt.buff +850 ha->reset_tmplt.hdr->start_seq_offset;851 ha->reset_tmplt.stop_offset = ha->reset_tmplt.buff +852 ha->reset_tmplt.hdr->hdr_size;853 qla4_83xx_dump_reset_seq_hdr(ha);854 855 goto exit_read_reset_template;856 857exit_read_template_error:858 vfree(ha->reset_tmplt.buff);859 860exit_read_reset_template:861 return;862}863 864/**865 * qla4_83xx_read_write_crb_reg - Read from raddr and write value to waddr.866 *867 * @ha : Pointer to adapter structure868 * @raddr : CRB address to read from869 * @waddr : CRB address to write to870 **/871static void qla4_83xx_read_write_crb_reg(struct scsi_qla_host *ha,872 uint32_t raddr, uint32_t waddr)873{874 uint32_t value;875 876 qla4_83xx_rd_reg_indirect(ha, raddr, &value);877 qla4_83xx_wr_reg_indirect(ha, waddr, value);878}879 880/**881 * qla4_83xx_rmw_crb_reg - Read Modify Write crb register882 *883 * This function read value from raddr, AND with test_mask,884 * Shift Left,Right/OR/XOR with values RMW header and write value to waddr.885 *886 * @ha : Pointer to adapter structure887 * @raddr : CRB address to read from888 * @waddr : CRB address to write to889 * @p_rmw_hdr : header with shift/or/xor values.890 **/891static void qla4_83xx_rmw_crb_reg(struct scsi_qla_host *ha, uint32_t raddr,892 uint32_t waddr,893 struct qla4_83xx_rmw *p_rmw_hdr)894{895 uint32_t value;896 897 if (p_rmw_hdr->index_a)898 value = ha->reset_tmplt.array[p_rmw_hdr->index_a];899 else900 qla4_83xx_rd_reg_indirect(ha, raddr, &value);901 902 value &= p_rmw_hdr->test_mask;903 value <<= p_rmw_hdr->shl;904 value >>= p_rmw_hdr->shr;905 value |= p_rmw_hdr->or_value;906 value ^= p_rmw_hdr->xor_value;907 908 qla4_83xx_wr_reg_indirect(ha, waddr, value);909 910 return;911}912 913static void qla4_83xx_write_list(struct scsi_qla_host *ha,914 struct qla4_83xx_reset_entry_hdr *p_hdr)915{916 struct qla4_83xx_entry *p_entry;917 uint32_t i;918 919 p_entry = (struct qla4_83xx_entry *)920 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));921 922 for (i = 0; i < p_hdr->count; i++, p_entry++) {923 qla4_83xx_wr_reg_indirect(ha, p_entry->arg1, p_entry->arg2);924 if (p_hdr->delay)925 udelay((uint32_t)(p_hdr->delay));926 }927}928 929static void qla4_83xx_read_write_list(struct scsi_qla_host *ha,930 struct qla4_83xx_reset_entry_hdr *p_hdr)931{932 struct qla4_83xx_entry *p_entry;933 uint32_t i;934 935 p_entry = (struct qla4_83xx_entry *)936 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));937 938 for (i = 0; i < p_hdr->count; i++, p_entry++) {939 qla4_83xx_read_write_crb_reg(ha, p_entry->arg1, p_entry->arg2);940 if (p_hdr->delay)941 udelay((uint32_t)(p_hdr->delay));942 }943}944 945static void qla4_83xx_poll_list(struct scsi_qla_host *ha,946 struct qla4_83xx_reset_entry_hdr *p_hdr)947{948 long delay;949 struct qla4_83xx_entry *p_entry;950 struct qla4_83xx_poll *p_poll;951 uint32_t i;952 uint32_t value;953 954 p_poll = (struct qla4_83xx_poll *)955 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));956 957 /* Entries start after 8 byte qla4_83xx_poll, poll header contains958 * the test_mask, test_value. */959 p_entry = (struct qla4_83xx_entry *)((char *)p_poll +960 sizeof(struct qla4_83xx_poll));961 962 delay = (long)p_hdr->delay;963 if (!delay) {964 for (i = 0; i < p_hdr->count; i++, p_entry++) {965 qla4_83xx_poll_reg(ha, p_entry->arg1, delay,966 p_poll->test_mask,967 p_poll->test_value);968 }969 } else {970 for (i = 0; i < p_hdr->count; i++, p_entry++) {971 if (qla4_83xx_poll_reg(ha, p_entry->arg1, delay,972 p_poll->test_mask,973 p_poll->test_value)) {974 qla4_83xx_rd_reg_indirect(ha, p_entry->arg1,975 &value);976 qla4_83xx_rd_reg_indirect(ha, p_entry->arg2,977 &value);978 }979 }980 }981}982 983static void qla4_83xx_poll_write_list(struct scsi_qla_host *ha,984 struct qla4_83xx_reset_entry_hdr *p_hdr)985{986 long delay;987 struct qla4_83xx_quad_entry *p_entry;988 struct qla4_83xx_poll *p_poll;989 uint32_t i;990 991 p_poll = (struct qla4_83xx_poll *)992 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));993 p_entry = (struct qla4_83xx_quad_entry *)994 ((char *)p_poll + sizeof(struct qla4_83xx_poll));995 delay = (long)p_hdr->delay;996 997 for (i = 0; i < p_hdr->count; i++, p_entry++) {998 qla4_83xx_wr_reg_indirect(ha, p_entry->dr_addr,999 p_entry->dr_value);1000 qla4_83xx_wr_reg_indirect(ha, p_entry->ar_addr,1001 p_entry->ar_value);1002 if (delay) {1003 if (qla4_83xx_poll_reg(ha, p_entry->ar_addr, delay,1004 p_poll->test_mask,1005 p_poll->test_value)) {1006 DEBUG2(ql4_printk(KERN_INFO, ha,1007 "%s: Timeout Error: poll list, item_num %d, entry_num %d\n",1008 __func__, i,1009 ha->reset_tmplt.seq_index));1010 }1011 }1012 }1013}1014 1015static void qla4_83xx_read_modify_write(struct scsi_qla_host *ha,1016 struct qla4_83xx_reset_entry_hdr *p_hdr)1017{1018 struct qla4_83xx_entry *p_entry;1019 struct qla4_83xx_rmw *p_rmw_hdr;1020 uint32_t i;1021 1022 p_rmw_hdr = (struct qla4_83xx_rmw *)1023 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));1024 p_entry = (struct qla4_83xx_entry *)1025 ((char *)p_rmw_hdr + sizeof(struct qla4_83xx_rmw));1026 1027 for (i = 0; i < p_hdr->count; i++, p_entry++) {1028 qla4_83xx_rmw_crb_reg(ha, p_entry->arg1, p_entry->arg2,1029 p_rmw_hdr);1030 if (p_hdr->delay)1031 udelay((uint32_t)(p_hdr->delay));1032 }1033}1034 1035static void qla4_83xx_pause(struct scsi_qla_host *ha,1036 struct qla4_83xx_reset_entry_hdr *p_hdr)1037{1038 if (p_hdr->delay)1039 mdelay((uint32_t)((long)p_hdr->delay));1040}1041 1042static void qla4_83xx_poll_read_list(struct scsi_qla_host *ha,1043 struct qla4_83xx_reset_entry_hdr *p_hdr)1044{1045 long delay;1046 int index;1047 struct qla4_83xx_quad_entry *p_entry;1048 struct qla4_83xx_poll *p_poll;1049 uint32_t i;1050 uint32_t value;1051 1052 p_poll = (struct qla4_83xx_poll *)1053 ((char *)p_hdr + sizeof(struct qla4_83xx_reset_entry_hdr));1054 p_entry = (struct qla4_83xx_quad_entry *)1055 ((char *)p_poll + sizeof(struct qla4_83xx_poll));1056 delay = (long)p_hdr->delay;1057 1058 for (i = 0; i < p_hdr->count; i++, p_entry++) {1059 qla4_83xx_wr_reg_indirect(ha, p_entry->ar_addr,1060 p_entry->ar_value);1061 if (delay) {1062 if (qla4_83xx_poll_reg(ha, p_entry->ar_addr, delay,1063 p_poll->test_mask,1064 p_poll->test_value)) {1065 DEBUG2(ql4_printk(KERN_INFO, ha,1066 "%s: Timeout Error: poll list, Item_num %d, entry_num %d\n",1067 __func__, i,1068 ha->reset_tmplt.seq_index));1069 } else {1070 index = ha->reset_tmplt.array_index;1071 qla4_83xx_rd_reg_indirect(ha, p_entry->dr_addr,1072 &value);1073 ha->reset_tmplt.array[index++] = value;1074 1075 if (index == QLA83XX_MAX_RESET_SEQ_ENTRIES)1076 ha->reset_tmplt.array_index = 1;1077 }1078 }1079 }1080}1081 1082static void qla4_83xx_seq_end(struct scsi_qla_host *ha,1083 struct qla4_83xx_reset_entry_hdr *p_hdr)1084{1085 ha->reset_tmplt.seq_end = 1;1086}1087 1088static void qla4_83xx_template_end(struct scsi_qla_host *ha,1089 struct qla4_83xx_reset_entry_hdr *p_hdr)1090{1091 ha->reset_tmplt.template_end = 1;1092 1093 if (ha->reset_tmplt.seq_error == 0) {1094 DEBUG2(ql4_printk(KERN_INFO, ha,1095 "%s: Reset sequence completed SUCCESSFULLY.\n",1096 __func__));1097 } else {1098 ql4_printk(KERN_ERR, ha, "%s: Reset sequence completed with some timeout errors.\n",1099 __func__);1100 }1101}1102 1103/**1104 * qla4_83xx_process_reset_template - Process reset template.1105 *1106 * Process all entries in reset template till entry with SEQ_END opcode,1107 * which indicates end of the reset template processing. Each entry has a1108 * Reset Entry header, entry opcode/command, with size of the entry, number1109 * of entries in sub-sequence and delay in microsecs or timeout in millisecs.1110 *1111 * @ha : Pointer to adapter structure1112 * @p_buff : Common reset entry header.1113 **/1114static void qla4_83xx_process_reset_template(struct scsi_qla_host *ha,1115 char *p_buff)1116{1117 int index, entries;1118 struct qla4_83xx_reset_entry_hdr *p_hdr;1119 char *p_entry = p_buff;1120 1121 ha->reset_tmplt.seq_end = 0;1122 ha->reset_tmplt.template_end = 0;1123 entries = ha->reset_tmplt.hdr->entries;1124 index = ha->reset_tmplt.seq_index;1125 1126 for (; (!ha->reset_tmplt.seq_end) && (index < entries); index++) {1127 1128 p_hdr = (struct qla4_83xx_reset_entry_hdr *)p_entry;1129 switch (p_hdr->cmd) {1130 case OPCODE_NOP:1131 break;1132 case OPCODE_WRITE_LIST:1133 qla4_83xx_write_list(ha, p_hdr);1134 break;1135 case OPCODE_READ_WRITE_LIST:1136 qla4_83xx_read_write_list(ha, p_hdr);1137 break;1138 case OPCODE_POLL_LIST:1139 qla4_83xx_poll_list(ha, p_hdr);1140 break;1141 case OPCODE_POLL_WRITE_LIST:1142 qla4_83xx_poll_write_list(ha, p_hdr);1143 break;1144 case OPCODE_READ_MODIFY_WRITE:1145 qla4_83xx_read_modify_write(ha, p_hdr);1146 break;1147 case OPCODE_SEQ_PAUSE:1148 qla4_83xx_pause(ha, p_hdr);1149 break;1150 case OPCODE_SEQ_END:1151 qla4_83xx_seq_end(ha, p_hdr);1152 break;1153 case OPCODE_TMPL_END:1154 qla4_83xx_template_end(ha, p_hdr);1155 break;1156 case OPCODE_POLL_READ_LIST:1157 qla4_83xx_poll_read_list(ha, p_hdr);1158 break;1159 default:1160 ql4_printk(KERN_ERR, ha, "%s: Unknown command ==> 0x%04x on entry = %d\n",1161 __func__, p_hdr->cmd, index);1162 break;1163 }1164 1165 /* Set pointer to next entry in the sequence. */1166 p_entry += p_hdr->size;1167 }1168 1169 ha->reset_tmplt.seq_index = index;1170}1171 1172static void qla4_83xx_process_stop_seq(struct scsi_qla_host *ha)1173{1174 ha->reset_tmplt.seq_index = 0;1175 qla4_83xx_process_reset_template(ha, ha->reset_tmplt.stop_offset);1176 1177 if (ha->reset_tmplt.seq_end != 1)1178 ql4_printk(KERN_ERR, ha, "%s: Abrupt STOP Sub-Sequence end.\n",1179 __func__);1180}1181 1182static void qla4_83xx_process_start_seq(struct scsi_qla_host *ha)1183{1184 qla4_83xx_process_reset_template(ha, ha->reset_tmplt.start_offset);1185 1186 if (ha->reset_tmplt.template_end != 1)1187 ql4_printk(KERN_ERR, ha, "%s: Abrupt START Sub-Sequence end.\n",1188 __func__);1189}1190 1191static void qla4_83xx_process_init_seq(struct scsi_qla_host *ha)1192{1193 qla4_83xx_process_reset_template(ha, ha->reset_tmplt.init_offset);1194 1195 if (ha->reset_tmplt.seq_end != 1)1196 ql4_printk(KERN_ERR, ha, "%s: Abrupt INIT Sub-Sequence end.\n",1197 __func__);1198}1199 1200static int qla4_83xx_restart(struct scsi_qla_host *ha)1201{1202 int ret_val = QLA_SUCCESS;1203 uint32_t idc_ctrl;1204 1205 qla4_83xx_process_stop_seq(ha);1206 1207 /*1208 * Collect minidump.1209 * If IDC_CTRL BIT1 is set, clear it on going to INIT state and1210 * don't collect minidump1211 */1212 idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);1213 if (idc_ctrl & GRACEFUL_RESET_BIT1) {1214 qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL,1215 (idc_ctrl & ~GRACEFUL_RESET_BIT1));1216 ql4_printk(KERN_INFO, ha, "%s: Graceful RESET: Not collecting minidump\n",1217 __func__);1218 } else {1219 qla4_8xxx_get_minidump(ha);1220 }1221 1222 qla4_83xx_process_init_seq(ha);1223 1224 if (qla4_83xx_copy_bootloader(ha)) {1225 ql4_printk(KERN_ERR, ha, "%s: Copy bootloader, firmware restart failed!\n",1226 __func__);1227 ret_val = QLA_ERROR;1228 goto exit_restart;1229 }1230 1231 qla4_83xx_wr_reg(ha, QLA83XX_FW_IMAGE_VALID, QLA83XX_BOOT_FROM_FLASH);1232 qla4_83xx_process_start_seq(ha);1233 1234exit_restart:1235 return ret_val;1236}1237 1238int qla4_83xx_start_firmware(struct scsi_qla_host *ha)1239{1240 int ret_val = QLA_SUCCESS;1241 1242 ret_val = qla4_83xx_restart(ha);1243 if (ret_val == QLA_ERROR) {1244 ql4_printk(KERN_ERR, ha, "%s: Restart error\n", __func__);1245 goto exit_start_fw;1246 } else {1247 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Restart done\n",1248 __func__));1249 }1250 1251 ret_val = qla4_83xx_check_cmd_peg_status(ha);1252 if (ret_val == QLA_ERROR)1253 ql4_printk(KERN_ERR, ha, "%s: Peg not initialized\n",1254 __func__);1255 1256exit_start_fw:1257 return ret_val;1258}1259 1260/*----------------------Interrupt Related functions ---------------------*/1261 1262static void qla4_83xx_disable_iocb_intrs(struct scsi_qla_host *ha)1263{1264 if (test_and_clear_bit(AF_83XX_IOCB_INTR_ON, &ha->flags))1265 qla4_8xxx_intr_disable(ha);1266}1267 1268static void qla4_83xx_disable_mbox_intrs(struct scsi_qla_host *ha)1269{1270 uint32_t mb_int, ret;1271 1272 if (test_and_clear_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {1273 ret = readl(&ha->qla4_83xx_reg->mbox_int);1274 mb_int = ret & ~INT_ENABLE_FW_MB;1275 writel(mb_int, &ha->qla4_83xx_reg->mbox_int);1276 writel(1, &ha->qla4_83xx_reg->leg_int_mask);1277 }1278}1279 1280void qla4_83xx_disable_intrs(struct scsi_qla_host *ha)1281{1282 qla4_83xx_disable_mbox_intrs(ha);1283 qla4_83xx_disable_iocb_intrs(ha);1284}1285 1286static void qla4_83xx_enable_iocb_intrs(struct scsi_qla_host *ha)1287{1288 if (!test_bit(AF_83XX_IOCB_INTR_ON, &ha->flags)) {1289 qla4_8xxx_intr_enable(ha);1290 set_bit(AF_83XX_IOCB_INTR_ON, &ha->flags);1291 }1292}1293 1294void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha)1295{1296 uint32_t mb_int;1297 1298 if (!test_bit(AF_83XX_MBOX_INTR_ON, &ha->flags)) {1299 mb_int = INT_ENABLE_FW_MB;1300 writel(mb_int, &ha->qla4_83xx_reg->mbox_int);1301 writel(0, &ha->qla4_83xx_reg->leg_int_mask);1302 set_bit(AF_83XX_MBOX_INTR_ON, &ha->flags);1303 }1304}1305 1306 1307void qla4_83xx_enable_intrs(struct scsi_qla_host *ha)1308{1309 qla4_83xx_enable_mbox_intrs(ha);1310 qla4_83xx_enable_iocb_intrs(ha);1311}1312 1313 1314void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,1315 int incount)1316{1317 int i;1318 1319 /* Load all mailbox registers, except mailbox 0. */1320 for (i = 1; i < incount; i++)1321 writel(mbx_cmd[i], &ha->qla4_83xx_reg->mailbox_in[i]);1322 1323 writel(mbx_cmd[0], &ha->qla4_83xx_reg->mailbox_in[0]);1324 1325 /* Set Host Interrupt register to 1, to tell the firmware that1326 * a mailbox command is pending. Firmware after reading the1327 * mailbox command, clears the host interrupt register */1328 writel(HINT_MBX_INT_PENDING, &ha->qla4_83xx_reg->host_intr);1329}1330 1331void qla4_83xx_process_mbox_intr(struct scsi_qla_host *ha, int outcount)1332{1333 int intr_status;1334 1335 intr_status = readl(&ha->qla4_83xx_reg->risc_intr);1336 if (intr_status) {1337 ha->mbox_status_count = outcount;1338 ha->isp_ops->interrupt_service_routine(ha, intr_status);1339 }1340}1341 1342/**1343 * qla4_83xx_isp_reset - Resets ISP and aborts all outstanding commands.1344 * @ha: pointer to host adapter structure.1345 **/1346int qla4_83xx_isp_reset(struct scsi_qla_host *ha)1347{1348 int rval;1349 uint32_t dev_state;1350 1351 ha->isp_ops->idc_lock(ha);1352 dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);1353 1354 if (ql4xdontresethba)1355 qla4_83xx_set_idc_dontreset(ha);1356 1357 if (dev_state == QLA8XXX_DEV_READY) {1358 /* If IDC_CTRL DONTRESETHBA_BIT0 is set dont do reset1359 * recovery */1360 if (qla4_83xx_idc_dontreset(ha) == DONTRESET_BIT0) {1361 ql4_printk(KERN_ERR, ha, "%s: Reset recovery disabled\n",1362 __func__);1363 rval = QLA_ERROR;1364 goto exit_isp_reset;1365 }1366 1367 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: HW State: NEED RESET\n",1368 __func__));1369 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,1370 QLA8XXX_DEV_NEED_RESET);1371 1372 } else {1373 /* If device_state is NEED_RESET, go ahead with1374 * Reset,irrespective of ql4xdontresethba. This is to allow a1375 * non-reset-owner to force a reset. Non-reset-owner sets1376 * the IDC_CTRL BIT0 to prevent Reset-owner from doing a Reset1377 * and then forces a Reset by setting device_state to1378 * NEED_RESET. */1379 DEBUG2(ql4_printk(KERN_INFO, ha,1380 "%s: HW state already set to NEED_RESET\n",1381 __func__));1382 }1383 1384 /* For ISP8324 and ISP8042, Reset owner is NIC, iSCSI or FCOE based on1385 * priority and which drivers are present. Unlike ISP8022, the function1386 * setting NEED_RESET, may not be the Reset owner. */1387 if (qla4_83xx_can_perform_reset(ha))1388 set_bit(AF_8XXX_RST_OWNER, &ha->flags);1389 1390 ha->isp_ops->idc_unlock(ha);1391 rval = qla4_8xxx_device_state_handler(ha);1392 1393 ha->isp_ops->idc_lock(ha);1394 qla4_8xxx_clear_rst_ready(ha);1395exit_isp_reset:1396 ha->isp_ops->idc_unlock(ha);1397 1398 if (rval == QLA_SUCCESS)1399 clear_bit(AF_FW_RECOVERY, &ha->flags);1400 1401 return rval;1402}1403 1404static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha)1405{1406 u32 val = 0, val1 = 0;1407 int i;1408 1409 qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val);1410 DEBUG2(ql4_printk(KERN_INFO, ha, "SRE-Shim Ctrl:0x%x\n", val));1411 1412 /* Port 0 Rx Buffer Pause Threshold Registers. */1413 DEBUG2(ql4_printk(KERN_INFO, ha,1414 "Port 0 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));1415 for (i = 0; i < 8; i++) {1416 qla4_83xx_rd_reg_indirect(ha,1417 QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4), &val);1418 DEBUG2(pr_info("0x%x ", val));1419 }1420 1421 DEBUG2(pr_info("\n"));1422 1423 /* Port 1 Rx Buffer Pause Threshold Registers. */1424 DEBUG2(ql4_printk(KERN_INFO, ha,1425 "Port 1 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));1426 for (i = 0; i < 8; i++) {1427 qla4_83xx_rd_reg_indirect(ha,1428 QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4), &val);1429 DEBUG2(pr_info("0x%x ", val));1430 }1431 1432 DEBUG2(pr_info("\n"));1433 1434 /* Port 0 RxB Traffic Class Max Cell Registers. */1435 DEBUG2(ql4_printk(KERN_INFO, ha,1436 "Port 0 RxB Traffic Class Max Cell Registers[3..0]:"));1437 for (i = 0; i < 4; i++) {1438 qla4_83xx_rd_reg_indirect(ha,1439 QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4), &val);1440 DEBUG2(pr_info("0x%x ", val));1441 }1442 1443 DEBUG2(pr_info("\n"));1444 1445 /* Port 1 RxB Traffic Class Max Cell Registers. */1446 DEBUG2(ql4_printk(KERN_INFO, ha,1447 "Port 1 RxB Traffic Class Max Cell Registers[3..0]:"));1448 for (i = 0; i < 4; i++) {1449 qla4_83xx_rd_reg_indirect(ha,1450 QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4), &val);1451 DEBUG2(pr_info("0x%x ", val));1452 }1453 1454 DEBUG2(pr_info("\n"));1455 1456 /* Port 0 RxB Rx Traffic Class Stats. */1457 DEBUG2(ql4_printk(KERN_INFO, ha,1458 "Port 0 RxB Rx Traffic Class Stats [TC7..TC0]"));1459 for (i = 7; i >= 0; i--) {1460 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val);1461 val &= ~(0x7 << 29); /* Reset bits 29 to 31 */1462 qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS,1463 (val | (i << 29)));1464 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val);1465 DEBUG2(pr_info("0x%x ", val));1466 }1467 1468 DEBUG2(pr_info("\n"));1469 1470 /* Port 1 RxB Rx Traffic Class Stats. */1471 DEBUG2(ql4_printk(KERN_INFO, ha,1472 "Port 1 RxB Rx Traffic Class Stats [TC7..TC0]"));1473 for (i = 7; i >= 0; i--) {1474 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val);1475 val &= ~(0x7 << 29); /* Reset bits 29 to 31 */1476 qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS,1477 (val | (i << 29)));1478 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val);1479 DEBUG2(pr_info("0x%x ", val));1480 }1481 1482 DEBUG2(pr_info("\n"));1483 1484 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS, &val);1485 qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS, &val1);1486 1487 DEBUG2(ql4_printk(KERN_INFO, ha,1488 "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",1489 val, val1));1490}1491 1492static void __qla4_83xx_disable_pause(struct scsi_qla_host *ha)1493{1494 int i;1495 1496 /* set SRE-Shim Control Register */1497 qla4_83xx_wr_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL,1498 QLA83XX_SET_PAUSE_VAL);1499 1500 for (i = 0; i < 8; i++) {1501 /* Port 0 Rx Buffer Pause Threshold Registers. */1502 qla4_83xx_wr_reg_indirect(ha,1503 QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4),1504 QLA83XX_SET_PAUSE_VAL);1505 /* Port 1 Rx Buffer Pause Threshold Registers. */1506 qla4_83xx_wr_reg_indirect(ha,1507 QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4),1508 QLA83XX_SET_PAUSE_VAL);1509 }1510 1511 for (i = 0; i < 4; i++) {1512 /* Port 0 RxB Traffic Class Max Cell Registers. */1513 qla4_83xx_wr_reg_indirect(ha,1514 QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4),1515 QLA83XX_SET_TC_MAX_CELL_VAL);1516 /* Port 1 RxB Traffic Class Max Cell Registers. */1517 qla4_83xx_wr_reg_indirect(ha,1518 QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4),1519 QLA83XX_SET_TC_MAX_CELL_VAL);1520 }1521 1522 qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS,1523 QLA83XX_SET_PAUSE_VAL);1524 qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS,1525 QLA83XX_SET_PAUSE_VAL);1526 1527 ql4_printk(KERN_INFO, ha, "Disabled pause frames successfully.\n");1528}1529 1530/**1531 * qla4_83xx_eport_init - Initialize EPort.1532 * @ha: Pointer to host adapter structure.1533 *1534 * If EPort hardware is in reset state before disabling pause, there would be1535 * serious hardware wedging issues. To prevent this perform eport init everytime1536 * before disabling pause frames.1537 **/1538static void qla4_83xx_eport_init(struct scsi_qla_host *ha)1539{1540 /* Clear the 8 registers */1541 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_REG, 0x0);1542 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT0, 0x0);1543 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT1, 0x0);1544 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT2, 0x0);1545 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT3, 0x0);1546 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_SRE_SHIM, 0x0);1547 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_EPG_SHIM, 0x0);1548 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_ETHER_PCS, 0x0);1549 1550 /* Write any value to Reset Control register */1551 qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_CONTROL, 0xFF);1552 1553 ql4_printk(KERN_INFO, ha, "EPORT is out of reset.\n");1554}1555 1556void qla4_83xx_disable_pause(struct scsi_qla_host *ha)1557{1558 ha->isp_ops->idc_lock(ha);1559 /* Before disabling pause frames, ensure that eport is not in reset */1560 qla4_83xx_eport_init(ha);1561 qla4_83xx_dump_pause_control_regs(ha);1562 __qla4_83xx_disable_pause(ha);1563 ha->isp_ops->idc_unlock(ha);1564}1565 1566/**1567 * qla4_83xx_is_detached - Check if we are marked invisible.1568 * @ha: Pointer to host adapter structure.1569 **/1570int qla4_83xx_is_detached(struct scsi_qla_host *ha)1571{1572 uint32_t drv_active;1573 1574 drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);1575 1576 if (test_bit(AF_INIT_DONE, &ha->flags) &&1577 !(drv_active & (1 << ha->func_num))) {1578 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: drv_active = 0x%X\n",1579 __func__, drv_active));1580 return QLA_SUCCESS;1581 }1582 1583 return QLA_ERROR;1584}1585