/*
* QLogic qlcnic NIC Driver
* Copyright (c) 2009-2010 QLogic Corporation
*
* See LICENSE.qlcnic for copyright and licensing details.
*/
#include "qlcnic.h"
static u32
qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
{
u32 rsp;
int timeout = 0;
do {
/* give atleast 1ms for firmware to respond */
msleep(1);
if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
return QLCNIC_CDRP_RSP_TIMEOUT;
rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET);
} while (!QLCNIC_CDRP_IS_RSP(rsp));
return rsp;
}
void
qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
{
u32 rsp;
u32 signature;
struct pci_dev *pdev = adapter->pdev;
struct qlcnic_hardware_context *ahw = adapter->ahw;
signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func,
adapter->fw_hal_version);
/* Acquire semaphore before accessing CRB */
if (qlcnic_api_lock(adapter)) {
cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
return;
}
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, cmd->req.arg1);
QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, cmd->req.arg2);
QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, cmd->req.arg3);
QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
QLCNIC_CDRP_FORM_CMD(cmd->req.cmd));
rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
dev_err(&pdev->dev, "card response timeout.\n");
cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
dev_err(&pdev->dev, "failed card response code:0x%x\n",
cmd->rsp.cmd);
} else if (rsp == QLCNIC_CDRP_RSP_OK) {
cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS;
if (cmd->rsp.arg2)
cmd->rsp.arg2 = QLCRD32(adapter,
QLCNIC_ARG2_CRB_OFFSET);
if (cmd->rsp.arg3)
cmd->rsp.arg3 = QLCRD32(adapter,
QLCNIC_ARG3_CRB_OFFSET);
}
if (cmd->rsp.arg1)
cmd->rsp.arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
/* Release semaphore */
qlcnic_api_unlock(adapter);
}
static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
{
uint64_t sum = 0;
int count = temp_size / sizeof(uint32_t);
while (count-- > 0)
sum += *temp_buffer++;
while (sum >> 32)
sum = (sum & 0xFFFFFFFF) + (sum >> 32);
return ~sum;
}
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
{
int err, i;
u16 temp_size;
void *tmp_addr;
u32 version, csum, *template, *tmp_buf;
struct qlcnic_cmd_args cmd;
struct qlcnic_hardware_context *ahw;
struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
dma_addr_t tmp_addr_t = 0;
ahw = adapter->ahw;