static int qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) { int ret = 0; struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) { netdev_info(netdev, "Forcing a FW dump\n"); qlcnic_dev_request_reset(adapter); } else { if (val->flag > QLCNIC_DUMP_MASK_MAX || val->flag < QLCNIC_DUMP_MASK_MIN) { netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); ret = -EINVAL; goto out; } if (qlcnic_api_lock(adapter)) return -EIO; fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff; qlcnic_api_unlock(adapter); netdev_info(netdev, "Driver mask changed to: 0x%x\n", fw_dump->tmpl_hdr->drv_cap_mask); } out: return ret; }
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 int qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, void *buffer) { int i, copy_sz; u32 *hdr_ptr, *data; struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; if (qlcnic_api_lock(adapter)) return -EIO; if (!fw_dump->clr) { netdev_info(netdev, "Dump not available\n"); qlcnic_api_unlock(adapter); return -EINVAL; } /* Copy template header first */ copy_sz = fw_dump->tmpl_hdr->size; hdr_ptr = (u32 *) fw_dump->tmpl_hdr; data = (u32 *) buffer; for (i = 0; i < copy_sz/sizeof(u32); i++) *data++ = cpu_to_le32(*hdr_ptr++); /* Copy captured dump data */ memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); dump->len = copy_sz + fw_dump->size; dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; /* Free dump area once data has been captured */ vfree(fw_dump->data); fw_dump->data = NULL; fw_dump->clr = 0; qlcnic_api_unlock(adapter); return 0; }