/*
* 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;
}
u32
qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
{
u32 rsp;
u32 signature;
u32 rcode = QLCNIC_RCODE_SUCCESS;
struct pci_dev *pdev = adapter->pdev;
signature = QLCNIC_CDRP_SIGNATURE_MAKE(pci_fn, version);
/* Acquire semaphore before accessing CRB */
if (qlcnic_api_lock(adapter))
return QLCNIC_RCODE_TIMEOUT;
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, arg1);
QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, arg2);
QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, arg3);
QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, QLCNIC_CDRP_FORM_CMD(cmd));
rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
dev_err(&pdev->dev, "card response timeout.\n");
rcode = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
rcode = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
dev_err(&pdev->dev, "failed card response code:0x%x\n",
rcode);
}
/* Release semaphore */
qlcnic_api_unlock(adapter);
return rcode;
}
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_hardware_context *ahw;
struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
dma_addr_t tmp_addr_t = 0;
ahw = adapter->ahw;
err = qlcnic_issue_cmd(adapter,
adapter->ahw->pci_func,
adapter->fw_hal_version,
0,
0,
0,
QLCNIC_CDRP_CMD_TEMP_SIZE);
if (err != QLCNIC_RCODE_SUCCESS) {
err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
dev_err(&adapter->pdev->dev,
"Failed to get template size %d\n", err);
err = -EIO;
return err;
}
version = QLCRD32(adapter, QLCNIC_ARG3_CRB_OFFSET);
temp_size = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
if (!temp_size)
return -EIO;
tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,
&tmp_addr_t, GFP_KERNEL