1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2aa43c215SJeff Kirsher /*
3aa43c215SJeff Kirsher * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria * Copyright (c) 2009-2013 QLogic Corporation
5aa43c215SJeff Kirsher */
6aa43c215SJeff Kirsher
7aa43c215SJeff Kirsher #include "qlcnic.h"
8aa43c215SJeff Kirsher
97e2cf4feSSony Chacko static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
107e2cf4feSSony Chacko {QLCNIC_CMD_CREATE_RX_CTX, 4, 1},
117e2cf4feSSony Chacko {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
127e2cf4feSSony Chacko {QLCNIC_CMD_CREATE_TX_CTX, 4, 1},
13d47d2fddSRajesh Borundia {QLCNIC_CMD_DESTROY_TX_CTX, 3, 1},
147e2cf4feSSony Chacko {QLCNIC_CMD_INTRPT_TEST, 4, 1},
157e2cf4feSSony Chacko {QLCNIC_CMD_SET_MTU, 4, 1},
167e2cf4feSSony Chacko {QLCNIC_CMD_READ_PHY, 4, 2},
177e2cf4feSSony Chacko {QLCNIC_CMD_WRITE_PHY, 5, 1},
187e2cf4feSSony Chacko {QLCNIC_CMD_READ_HW_REG, 4, 1},
197e2cf4feSSony Chacko {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
207e2cf4feSSony Chacko {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
217e2cf4feSSony Chacko {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
227e2cf4feSSony Chacko {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
237e2cf4feSSony Chacko {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
247e2cf4feSSony Chacko {QLCNIC_CMD_GET_PCI_INFO, 4, 1},
257e2cf4feSSony Chacko {QLCNIC_CMD_GET_NIC_INFO, 4, 1},
267e2cf4feSSony Chacko {QLCNIC_CMD_SET_NIC_INFO, 4, 1},
277e2cf4feSSony Chacko {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
287e2cf4feSSony Chacko {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
297e2cf4feSSony Chacko {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
307e2cf4feSSony Chacko {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
317e2cf4feSSony Chacko {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
327e2cf4feSSony Chacko {QLCNIC_CMD_GET_MAC_STATS, 4, 1},
337e2cf4feSSony Chacko {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
342a1ef4b5SRajesh Borundia {QLCNIC_CMD_GET_ESWITCH_STATS, 4, 1},
357e2cf4feSSony Chacko {QLCNIC_CMD_CONFIG_PORT, 4, 1},
367e2cf4feSSony Chacko {QLCNIC_CMD_TEMP_SIZE, 4, 4},
377e2cf4feSSony Chacko {QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
388af3f33dSPratik Pujar {QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1},
39487042afSHimanshu Madhani {QLCNIC_CMD_GET_LED_STATUS, 4, 2},
40012ec812SHimanshu Madhani {QLCNIC_CMD_MQ_TX_CONFIG_INTR, 2, 3},
4114d385b9SSucheta Chakraborty {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
42fb859ed6SSucheta Chakraborty {QLCNIC_CMD_DCB_QUERY_PARAM, 4, 1},
437e2cf4feSSony Chacko };
447e2cf4feSSony Chacko
qlcnic_get_cmd_signature(struct qlcnic_hardware_context * ahw)457e2cf4feSSony Chacko static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
467e2cf4feSSony Chacko {
477e2cf4feSSony Chacko return (ahw->pci_func & 0xff) | ((ahw->fw_hal_version & 0xff) << 8) |
487e2cf4feSSony Chacko (0xcafe << 16);
497e2cf4feSSony Chacko }
507e2cf4feSSony Chacko
517e2cf4feSSony Chacko /* Allocate mailbox registers */
qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args * mbx,struct qlcnic_adapter * adapter,u32 type)527e2cf4feSSony Chacko int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
537e2cf4feSSony Chacko struct qlcnic_adapter *adapter, u32 type)
547e2cf4feSSony Chacko {
557e2cf4feSSony Chacko int i, size;
567e2cf4feSSony Chacko const struct qlcnic_mailbox_metadata *mbx_tbl;
577e2cf4feSSony Chacko
587e2cf4feSSony Chacko mbx_tbl = qlcnic_mbx_tbl;
597e2cf4feSSony Chacko size = ARRAY_SIZE(qlcnic_mbx_tbl);
607e2cf4feSSony Chacko for (i = 0; i < size; i++) {
617e2cf4feSSony Chacko if (type == mbx_tbl[i].cmd) {
627e2cf4feSSony Chacko mbx->req.num = mbx_tbl[i].in_args;
637e2cf4feSSony Chacko mbx->rsp.num = mbx_tbl[i].out_args;
647e2cf4feSSony Chacko mbx->req.arg = kcalloc(mbx->req.num,
657e2cf4feSSony Chacko sizeof(u32), GFP_ATOMIC);
667e2cf4feSSony Chacko if (!mbx->req.arg)
677e2cf4feSSony Chacko return -ENOMEM;
687e2cf4feSSony Chacko mbx->rsp.arg = kcalloc(mbx->rsp.num,
697e2cf4feSSony Chacko sizeof(u32), GFP_ATOMIC);
707e2cf4feSSony Chacko if (!mbx->rsp.arg) {
717e2cf4feSSony Chacko kfree(mbx->req.arg);
727e2cf4feSSony Chacko mbx->req.arg = NULL;
737e2cf4feSSony Chacko return -ENOMEM;
747e2cf4feSSony Chacko }
757e2cf4feSSony Chacko mbx->req.arg[0] = type;
767e2cf4feSSony Chacko break;
777e2cf4feSSony Chacko }
787e2cf4feSSony Chacko }
797e2cf4feSSony Chacko return 0;
807e2cf4feSSony Chacko }
817e2cf4feSSony Chacko
827e2cf4feSSony Chacko /* Free up mailbox registers */
qlcnic_free_mbx_args(struct qlcnic_cmd_args * cmd)837e2cf4feSSony Chacko void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
847e2cf4feSSony Chacko {
857e2cf4feSSony Chacko kfree(cmd->req.arg);
867e2cf4feSSony Chacko cmd->req.arg = NULL;
877e2cf4feSSony Chacko kfree(cmd->rsp.arg);
887e2cf4feSSony Chacko cmd->rsp.arg = NULL;
897e2cf4feSSony Chacko }
907e2cf4feSSony Chacko
91aa43c215SJeff Kirsher static u32
qlcnic_poll_rsp(struct qlcnic_adapter * adapter)92aa43c215SJeff Kirsher qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
93aa43c215SJeff Kirsher {
94aa43c215SJeff Kirsher u32 rsp;
954bd8e738SHimanshu Madhani int timeout = 0, err = 0;
96aa43c215SJeff Kirsher
97aa43c215SJeff Kirsher do {
98aa43c215SJeff Kirsher /* give atleast 1ms for firmware to respond */
9968b3f28cSNarendra K mdelay(1);
100aa43c215SJeff Kirsher
101aa43c215SJeff Kirsher if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
102aa43c215SJeff Kirsher return QLCNIC_CDRP_RSP_TIMEOUT;
103aa43c215SJeff Kirsher
1044bd8e738SHimanshu Madhani rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET, &err);
105aa43c215SJeff Kirsher } while (!QLCNIC_CDRP_IS_RSP(rsp));
106aa43c215SJeff Kirsher
107aa43c215SJeff Kirsher return rsp;
108aa43c215SJeff Kirsher }
109aa43c215SJeff Kirsher
qlcnic_82xx_issue_cmd(struct qlcnic_adapter * adapter,struct qlcnic_cmd_args * cmd)1107e2cf4feSSony Chacko int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
1117e2cf4feSSony Chacko struct qlcnic_cmd_args *cmd)
112aa43c215SJeff Kirsher {
1134bd8e738SHimanshu Madhani int i, err = 0;
114aa43c215SJeff Kirsher u32 rsp;
115aa43c215SJeff Kirsher u32 signature;
116aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
1177777de9aSAnirban Chakraborty struct qlcnic_hardware_context *ahw = adapter->ahw;
118114ef38aSJitendra Kalsaria const char *fmt;
119aa43c215SJeff Kirsher
1207e2cf4feSSony Chacko signature = qlcnic_get_cmd_signature(ahw);
121aa43c215SJeff Kirsher
122aa43c215SJeff Kirsher /* Acquire semaphore before accessing CRB */
1237777de9aSAnirban Chakraborty if (qlcnic_api_lock(adapter)) {
1247e2cf4feSSony Chacko cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
1257e2cf4feSSony Chacko return cmd->rsp.arg[0];
1267777de9aSAnirban Chakraborty }
127aa43c215SJeff Kirsher
128aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
1292a1ef4b5SRajesh Borundia for (i = 1; i < cmd->req.num; i++)
1307e2cf4feSSony Chacko QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
1317777de9aSAnirban Chakraborty QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
1327e2cf4feSSony Chacko QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
133aa43c215SJeff Kirsher rsp = qlcnic_poll_rsp(adapter);
134aa43c215SJeff Kirsher
135aa43c215SJeff Kirsher if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
136bf63014fSRajesh Borundia dev_err(&pdev->dev, "command timeout, response = 0x%x\n", rsp);
1377e2cf4feSSony Chacko cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
138aa43c215SJeff Kirsher } else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
1394bd8e738SHimanshu Madhani cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
140114ef38aSJitendra Kalsaria switch (cmd->rsp.arg[0]) {
141114ef38aSJitendra Kalsaria case QLCNIC_RCODE_INVALID_ARGS:
142114ef38aSJitendra Kalsaria fmt = "CDRP invalid args: [%d]\n";
143114ef38aSJitendra Kalsaria break;
144114ef38aSJitendra Kalsaria case QLCNIC_RCODE_NOT_SUPPORTED:
145114ef38aSJitendra Kalsaria case QLCNIC_RCODE_NOT_IMPL:
146114ef38aSJitendra Kalsaria fmt = "CDRP command not supported: [%d]\n";
147114ef38aSJitendra Kalsaria break;
148114ef38aSJitendra Kalsaria case QLCNIC_RCODE_NOT_PERMITTED:
149114ef38aSJitendra Kalsaria fmt = "CDRP requested action not permitted: [%d]\n";
150114ef38aSJitendra Kalsaria break;
151114ef38aSJitendra Kalsaria case QLCNIC_RCODE_INVALID:
152114ef38aSJitendra Kalsaria fmt = "CDRP invalid or unknown cmd received: [%d]\n";
153114ef38aSJitendra Kalsaria break;
154114ef38aSJitendra Kalsaria case QLCNIC_RCODE_TIMEOUT:
155114ef38aSJitendra Kalsaria fmt = "CDRP command timeout: [%d]\n";
156114ef38aSJitendra Kalsaria break;
157114ef38aSJitendra Kalsaria default:
158114ef38aSJitendra Kalsaria fmt = "CDRP command failed: [%d]\n";
159114ef38aSJitendra Kalsaria break;
160114ef38aSJitendra Kalsaria }
161114ef38aSJitendra Kalsaria dev_err(&pdev->dev, fmt, cmd->rsp.arg[0]);
162012ec812SHimanshu Madhani qlcnic_dump_mbx(adapter, cmd);
1637e2cf4feSSony Chacko } else if (rsp == QLCNIC_CDRP_RSP_OK)
1647e2cf4feSSony Chacko cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
1657e2cf4feSSony Chacko
1667e2cf4feSSony Chacko for (i = 1; i < cmd->rsp.num; i++)
1674bd8e738SHimanshu Madhani cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i), &err);
168aa43c215SJeff Kirsher
169aa43c215SJeff Kirsher /* Release semaphore */
170aa43c215SJeff Kirsher qlcnic_api_unlock(adapter);
1717e2cf4feSSony Chacko return cmd->rsp.arg[0];
172aa43c215SJeff Kirsher }
173aa43c215SJeff Kirsher
qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter * adapter,u32 fw_cmd)1748af3f33dSPratik Pujar int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter, u32 fw_cmd)
175c84e340aSSritej Velaga {
176c84e340aSSritej Velaga struct qlcnic_cmd_args cmd;
177c84e340aSSritej Velaga u32 arg1, arg2, arg3;
178c84e340aSSritej Velaga char drv_string[12];
179c84e340aSSritej Velaga int err = 0;
180c84e340aSSritej Velaga
181c84e340aSSritej Velaga memset(drv_string, 0, sizeof(drv_string));
182c84e340aSSritej Velaga snprintf(drv_string, sizeof(drv_string), "%d"".""%d"".""%d",
183c84e340aSSritej Velaga _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR,
184c84e340aSSritej Velaga _QLCNIC_LINUX_SUBVERSION);
185c84e340aSSritej Velaga
1868af3f33dSPratik Pujar err = qlcnic_alloc_mbx_args(&cmd, adapter, fw_cmd);
187b6b4316cSShahed Shaikh if (err)
188b6b4316cSShahed Shaikh return err;
189b6b4316cSShahed Shaikh
190c84e340aSSritej Velaga memcpy(&arg1, drv_string, sizeof(u32));
191c84e340aSSritej Velaga memcpy(&arg2, drv_string + 4, sizeof(u32));
192c84e340aSSritej Velaga memcpy(&arg3, drv_string + 8, sizeof(u32));
193c84e340aSSritej Velaga
194c84e340aSSritej Velaga cmd.req.arg[1] = arg1;
195c84e340aSSritej Velaga cmd.req.arg[2] = arg2;
196c84e340aSSritej Velaga cmd.req.arg[3] = arg3;
197c84e340aSSritej Velaga
198c84e340aSSritej Velaga err = qlcnic_issue_cmd(adapter, &cmd);
199c84e340aSSritej Velaga if (err) {
200c84e340aSSritej Velaga dev_info(&adapter->pdev->dev,
201c84e340aSSritej Velaga "Failed to set driver version in firmware\n");
202f91bbcb0SHimanshu Madhani err = -EIO;
203c84e340aSSritej Velaga }
204f91bbcb0SHimanshu Madhani qlcnic_free_mbx_args(&cmd);
205f91bbcb0SHimanshu Madhani return err;
206c84e340aSSritej Velaga }
207c84e340aSSritej Velaga
208aa43c215SJeff Kirsher int
qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter * adapter,int mtu)209aa43c215SJeff Kirsher qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
210aa43c215SJeff Kirsher {
2117e2cf4feSSony Chacko int err = 0;
2127777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
213aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
214aa43c215SJeff Kirsher
2157e2cf4feSSony Chacko if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
2167e2cf4feSSony Chacko return err;
217b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU);
218b6b4316cSShahed Shaikh if (err)
219b6b4316cSShahed Shaikh return err;
220b6b4316cSShahed Shaikh
2217e2cf4feSSony Chacko cmd.req.arg[1] = recv_ctx->context_id;
2227e2cf4feSSony Chacko cmd.req.arg[2] = mtu;
2237e2cf4feSSony Chacko
2247e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
2257e2cf4feSSony Chacko if (err) {
226aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
2277e2cf4feSSony Chacko err = -EIO;
228aa43c215SJeff Kirsher }
2297e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
2307e2cf4feSSony Chacko return err;
231aa43c215SJeff Kirsher }
232aa43c215SJeff Kirsher
qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter * adapter)2337e2cf4feSSony Chacko int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
234aa43c215SJeff Kirsher {
235012ec812SHimanshu Madhani struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
236012ec812SHimanshu Madhani struct qlcnic_hardware_context *ahw = adapter->ahw;
237012ec812SHimanshu Madhani dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
238012ec812SHimanshu Madhani struct net_device *netdev = adapter->netdev;
239012ec812SHimanshu Madhani u32 temp_intr_crb_mode, temp_rds_crb_mode;
240aa43c215SJeff Kirsher struct qlcnic_cardrsp_rds_ring *prsp_rds;
241aa43c215SJeff Kirsher struct qlcnic_cardrsp_sds_ring *prsp_sds;
242012ec812SHimanshu Madhani struct qlcnic_hostrq_rds_ring *prq_rds;
243012ec812SHimanshu Madhani struct qlcnic_hostrq_sds_ring *prq_sds;
244aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
245aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
246012ec812SHimanshu Madhani struct qlcnic_cardrsp_rx_ctx *prsp;
247012ec812SHimanshu Madhani struct qlcnic_hostrq_rx_ctx *prq;
248aa43c215SJeff Kirsher u8 i, nrds_rings, nsds_rings;
249012ec812SHimanshu Madhani struct qlcnic_cmd_args cmd;
250aa43c215SJeff Kirsher size_t rq_size, rsp_size;
251aa43c215SJeff Kirsher u32 cap, reg, val, reg2;
252012ec812SHimanshu Madhani u64 phys_addr;
253012ec812SHimanshu Madhani u16 temp_u16;
254012ec812SHimanshu Madhani void *addr;
255aa43c215SJeff Kirsher int err;
256aa43c215SJeff Kirsher
257aa43c215SJeff Kirsher nrds_rings = adapter->max_rds_rings;
25834e8c406SHimanshu Madhani nsds_rings = adapter->drv_sds_rings;
259aa43c215SJeff Kirsher
260012ec812SHimanshu Madhani rq_size = SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
261aa43c215SJeff Kirsher nsds_rings);
262012ec812SHimanshu Madhani rsp_size = SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings,
263aa43c215SJeff Kirsher nsds_rings);
264aa43c215SJeff Kirsher
265aa43c215SJeff Kirsher addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
266aa43c215SJeff Kirsher &hostrq_phys_addr, GFP_KERNEL);
267aa43c215SJeff Kirsher if (addr == NULL)
268aa43c215SJeff Kirsher return -ENOMEM;
269aa43c215SJeff Kirsher prq = addr;
270aa43c215SJeff Kirsher
271aa43c215SJeff Kirsher addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
272aa43c215SJeff Kirsher &cardrsp_phys_addr, GFP_KERNEL);
273aa43c215SJeff Kirsher if (addr == NULL) {
274aa43c215SJeff Kirsher err = -ENOMEM;
275aa43c215SJeff Kirsher goto out_free_rq;
276aa43c215SJeff Kirsher }
277aa43c215SJeff Kirsher prsp = addr;
278aa43c215SJeff Kirsher
279aa43c215SJeff Kirsher prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
280aa43c215SJeff Kirsher
281aa43c215SJeff Kirsher cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN
282aa43c215SJeff Kirsher | QLCNIC_CAP0_VALIDOFF);
283aa43c215SJeff Kirsher cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
284aa43c215SJeff Kirsher
285c2c5e3a0SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) &&
286c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test) {
287012ec812SHimanshu Madhani cap |= QLCNIC_CAP0_TX_MULTI;
288012ec812SHimanshu Madhani } else {
2897e2cf4feSSony Chacko temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
2907e2cf4feSSony Chacko prq->valid_field_offset = cpu_to_le16(temp_u16);
291aa43c215SJeff Kirsher prq->txrx_sds_binding = nsds_rings - 1;
292012ec812SHimanshu Madhani temp_intr_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED;
293012ec812SHimanshu Madhani prq->host_int_crb_mode = cpu_to_le32(temp_intr_crb_mode);
294012ec812SHimanshu Madhani temp_rds_crb_mode = QLCNIC_HOST_RDS_CRB_MODE_UNIQUE;
295012ec812SHimanshu Madhani prq->host_rds_crb_mode = cpu_to_le32(temp_rds_crb_mode);
296012ec812SHimanshu Madhani }
297aa43c215SJeff Kirsher
298aa43c215SJeff Kirsher prq->capabilities[0] = cpu_to_le32(cap);
299aa43c215SJeff Kirsher
300aa43c215SJeff Kirsher prq->num_rds_rings = cpu_to_le16(nrds_rings);
301aa43c215SJeff Kirsher prq->num_sds_rings = cpu_to_le16(nsds_rings);
302aa43c215SJeff Kirsher prq->rds_ring_offset = 0;
303aa43c215SJeff Kirsher
304aa43c215SJeff Kirsher val = le32_to_cpu(prq->rds_ring_offset) +
305aa43c215SJeff Kirsher (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings);
306aa43c215SJeff Kirsher prq->sds_ring_offset = cpu_to_le32(val);
307aa43c215SJeff Kirsher
308aa43c215SJeff Kirsher prq_rds = (struct qlcnic_hostrq_rds_ring *)(prq->data +
309aa43c215SJeff Kirsher le32_to_cpu(prq->rds_ring_offset));
310aa43c215SJeff Kirsher
311aa43c215SJeff Kirsher for (i = 0; i < nrds_rings; i++) {
312aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[i];
313aa43c215SJeff Kirsher rds_ring->producer = 0;
314aa43c215SJeff Kirsher prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
315aa43c215SJeff Kirsher prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
316aa43c215SJeff Kirsher prq_rds[i].ring_kind = cpu_to_le32(i);
317aa43c215SJeff Kirsher prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
318aa43c215SJeff Kirsher }
319aa43c215SJeff Kirsher
320aa43c215SJeff Kirsher prq_sds = (struct qlcnic_hostrq_sds_ring *)(prq->data +
321aa43c215SJeff Kirsher le32_to_cpu(prq->sds_ring_offset));
322aa43c215SJeff Kirsher
323aa43c215SJeff Kirsher for (i = 0; i < nsds_rings; i++) {
324aa43c215SJeff Kirsher sds_ring = &recv_ctx->sds_rings[i];
325aa43c215SJeff Kirsher sds_ring->consumer = 0;
326aa43c215SJeff Kirsher memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));
327aa43c215SJeff Kirsher prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
328aa43c215SJeff Kirsher prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
329c2c5e3a0SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) &&
330c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test)
331012ec812SHimanshu Madhani prq_sds[i].msi_index = cpu_to_le16(ahw->intr_tbl[i].id);
332012ec812SHimanshu Madhani else
333aa43c215SJeff Kirsher prq_sds[i].msi_index = cpu_to_le16(i);
334aa43c215SJeff Kirsher }
335aa43c215SJeff Kirsher
336aa43c215SJeff Kirsher phys_addr = hostrq_phys_addr;
337b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX);
338b6b4316cSShahed Shaikh if (err)
339b6b4316cSShahed Shaikh goto out_free_rsp;
340b6b4316cSShahed Shaikh
3417e2cf4feSSony Chacko cmd.req.arg[1] = MSD(phys_addr);
3427e2cf4feSSony Chacko cmd.req.arg[2] = LSD(phys_addr);
3437e2cf4feSSony Chacko cmd.req.arg[3] = rq_size;
3447e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
345aa43c215SJeff Kirsher if (err) {
346aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
347aa43c215SJeff Kirsher "Failed to create rx ctx in firmware%d\n", err);
348aa43c215SJeff Kirsher goto out_free_rsp;
349aa43c215SJeff Kirsher }
350aa43c215SJeff Kirsher
351aa43c215SJeff Kirsher prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
352aa43c215SJeff Kirsher &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
353aa43c215SJeff Kirsher
354aa43c215SJeff Kirsher for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
355aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[i];
356aa43c215SJeff Kirsher reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
357012ec812SHimanshu Madhani rds_ring->crb_rcv_producer = ahw->pci_base0 + reg;
358aa43c215SJeff Kirsher }
359aa43c215SJeff Kirsher
360aa43c215SJeff Kirsher prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
361aa43c215SJeff Kirsher &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
362aa43c215SJeff Kirsher
363aa43c215SJeff Kirsher for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) {
364aa43c215SJeff Kirsher sds_ring = &recv_ctx->sds_rings[i];
365aa43c215SJeff Kirsher reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
366c2c5e3a0SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test)
367012ec812SHimanshu Madhani reg2 = ahw->intr_tbl[i].src;
368012ec812SHimanshu Madhani else
369aa43c215SJeff Kirsher reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);
370aa43c215SJeff Kirsher
371012ec812SHimanshu Madhani sds_ring->crb_intr_mask = ahw->pci_base0 + reg2;
372012ec812SHimanshu Madhani sds_ring->crb_sts_consumer = ahw->pci_base0 + reg;
373aa43c215SJeff Kirsher }
374aa43c215SJeff Kirsher
375aa43c215SJeff Kirsher recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
376aa43c215SJeff Kirsher recv_ctx->context_id = le16_to_cpu(prsp->context_id);
377aa43c215SJeff Kirsher recv_ctx->virt_port = prsp->virt_port;
378aa43c215SJeff Kirsher
379012ec812SHimanshu Madhani netdev_info(netdev, "Rx Context[%d] Created, state 0x%x\n",
380012ec812SHimanshu Madhani recv_ctx->context_id, recv_ctx->state);
381b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
382012ec812SHimanshu Madhani
383aa43c215SJeff Kirsher out_free_rsp:
384aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
385aa43c215SJeff Kirsher cardrsp_phys_addr);
386aa43c215SJeff Kirsher out_free_rq:
387aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
388012ec812SHimanshu Madhani
389aa43c215SJeff Kirsher return err;
390aa43c215SJeff Kirsher }
391aa43c215SJeff Kirsher
qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter * adapter)3927cb03b23SRajesh Borundia void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
393aa43c215SJeff Kirsher {
3947e2cf4feSSony Chacko int err;
3957777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
396aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
397aa43c215SJeff Kirsher
398b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX);
399b6b4316cSShahed Shaikh if (err)
400b6b4316cSShahed Shaikh return;
401b6b4316cSShahed Shaikh
4027e2cf4feSSony Chacko cmd.req.arg[1] = recv_ctx->context_id;
4037e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
4047e2cf4feSSony Chacko if (err)
405aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
406aa43c215SJeff Kirsher "Failed to destroy rx ctx in firmware\n");
407aa43c215SJeff Kirsher
408aa43c215SJeff Kirsher recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
4097e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
410aa43c215SJeff Kirsher }
411aa43c215SJeff Kirsher
qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter * adapter,struct qlcnic_host_tx_ring * tx_ring,int ring)4127e2cf4feSSony Chacko int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
4137e2cf4feSSony Chacko struct qlcnic_host_tx_ring *tx_ring,
4147e2cf4feSSony Chacko int ring)
415aa43c215SJeff Kirsher {
416012ec812SHimanshu Madhani struct qlcnic_hardware_context *ahw = adapter->ahw;
417012ec812SHimanshu Madhani struct net_device *netdev = adapter->netdev;
418aa43c215SJeff Kirsher struct qlcnic_hostrq_tx_ctx *prq;
419aa43c215SJeff Kirsher struct qlcnic_hostrq_cds_ring *prq_cds;
420aa43c215SJeff Kirsher struct qlcnic_cardrsp_tx_ctx *prsp;
421012ec812SHimanshu Madhani struct qlcnic_cmd_args cmd;
422012ec812SHimanshu Madhani u32 temp, intr_mask, temp_int_crb_mode;
423012ec812SHimanshu Madhani dma_addr_t rq_phys_addr, rsp_phys_addr;
424012ec812SHimanshu Madhani int temp_nsds_rings, index, err;
425aa43c215SJeff Kirsher void *rq_addr, *rsp_addr;
426aa43c215SJeff Kirsher size_t rq_size, rsp_size;
427aa43c215SJeff Kirsher u64 phys_addr;
428012ec812SHimanshu Madhani u16 msix_id;
429aa43c215SJeff Kirsher
430aa43c215SJeff Kirsher /* reset host resources */
431aa43c215SJeff Kirsher tx_ring->producer = 0;
432aa43c215SJeff Kirsher tx_ring->sw_consumer = 0;
433aa43c215SJeff Kirsher *(tx_ring->hw_consumer) = 0;
434aa43c215SJeff Kirsher
435aa43c215SJeff Kirsher rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
436750afb08SLuis Chamberlain rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
437ede23fa8SJoe Perches &rq_phys_addr, GFP_KERNEL);
438aa43c215SJeff Kirsher if (!rq_addr)
439aa43c215SJeff Kirsher return -ENOMEM;
440aa43c215SJeff Kirsher
441aa43c215SJeff Kirsher rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
442750afb08SLuis Chamberlain rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
443ede23fa8SJoe Perches &rsp_phys_addr, GFP_KERNEL);
444aa43c215SJeff Kirsher if (!rsp_addr) {
445aa43c215SJeff Kirsher err = -ENOMEM;
446aa43c215SJeff Kirsher goto out_free_rq;
447aa43c215SJeff Kirsher }
448aa43c215SJeff Kirsher
449aa43c215SJeff Kirsher prq = rq_addr;
450aa43c215SJeff Kirsher prsp = rsp_addr;
451aa43c215SJeff Kirsher
452aa43c215SJeff Kirsher prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
453aa43c215SJeff Kirsher
454aa43c215SJeff Kirsher temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN |
455aa43c215SJeff Kirsher QLCNIC_CAP0_LSO);
456c2c5e3a0SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test)
457012ec812SHimanshu Madhani temp |= QLCNIC_CAP0_TX_MULTI;
458012ec812SHimanshu Madhani
459aa43c215SJeff Kirsher prq->capabilities[0] = cpu_to_le32(temp);
460aa43c215SJeff Kirsher
461012ec812SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) &&
462c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test) {
46334e8c406SHimanshu Madhani temp_nsds_rings = adapter->drv_sds_rings;
464012ec812SHimanshu Madhani index = temp_nsds_rings + ring;
465012ec812SHimanshu Madhani msix_id = ahw->intr_tbl[index].id;
466012ec812SHimanshu Madhani prq->msi_index = cpu_to_le16(msix_id);
467012ec812SHimanshu Madhani } else {
468012ec812SHimanshu Madhani temp_int_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED;
469012ec812SHimanshu Madhani prq->host_int_crb_mode = cpu_to_le32(temp_int_crb_mode);
4707e2cf4feSSony Chacko prq->msi_index = 0;
471012ec812SHimanshu Madhani }
472aa43c215SJeff Kirsher
473aa43c215SJeff Kirsher prq->interrupt_ctl = 0;
474aa43c215SJeff Kirsher prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
475aa43c215SJeff Kirsher
476aa43c215SJeff Kirsher prq_cds = &prq->cds_ring;
477aa43c215SJeff Kirsher
478aa43c215SJeff Kirsher prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
479aa43c215SJeff Kirsher prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
480aa43c215SJeff Kirsher
481aa43c215SJeff Kirsher phys_addr = rq_phys_addr;
4827e2cf4feSSony Chacko
483b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
484b6b4316cSShahed Shaikh if (err)
485b6b4316cSShahed Shaikh goto out_free_rsp;
486b6b4316cSShahed Shaikh
4877e2cf4feSSony Chacko cmd.req.arg[1] = MSD(phys_addr);
4887e2cf4feSSony Chacko cmd.req.arg[2] = LSD(phys_addr);
4897e2cf4feSSony Chacko cmd.req.arg[3] = rq_size;
4907e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
491aa43c215SJeff Kirsher
492aa43c215SJeff Kirsher if (err == QLCNIC_RCODE_SUCCESS) {
493012ec812SHimanshu Madhani tx_ring->state = le32_to_cpu(prsp->host_ctx_state);
494aa43c215SJeff Kirsher temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
495aa43c215SJeff Kirsher tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
4967e2cf4feSSony Chacko tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
497012ec812SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) &&
498c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test &&
499012ec812SHimanshu Madhani (adapter->flags & QLCNIC_MSIX_ENABLED)) {
50034e8c406SHimanshu Madhani index = adapter->drv_sds_rings + ring;
501012ec812SHimanshu Madhani intr_mask = ahw->intr_tbl[index].src;
502012ec812SHimanshu Madhani tx_ring->crb_intr_mask = ahw->pci_base0 + intr_mask;
503aa43c215SJeff Kirsher }
504aa43c215SJeff Kirsher
505012ec812SHimanshu Madhani netdev_info(netdev, "Tx Context[0x%x] Created, state 0x%x\n",
506012ec812SHimanshu Madhani tx_ring->ctx_id, tx_ring->state);
507012ec812SHimanshu Madhani } else {
508012ec812SHimanshu Madhani netdev_err(netdev, "Failed to create tx ctx in firmware%d\n",
509012ec812SHimanshu Madhani err);
510012ec812SHimanshu Madhani err = -EIO;
511012ec812SHimanshu Madhani }
512b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
513b6b4316cSShahed Shaikh
514b6b4316cSShahed Shaikh out_free_rsp:
515aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
516aa43c215SJeff Kirsher rsp_phys_addr);
517aa43c215SJeff Kirsher out_free_rq:
518aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
519aa43c215SJeff Kirsher
520aa43c215SJeff Kirsher return err;
521aa43c215SJeff Kirsher }
522aa43c215SJeff Kirsher
qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter * adapter,struct qlcnic_host_tx_ring * tx_ring)5237cb03b23SRajesh Borundia void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
5247e2cf4feSSony Chacko struct qlcnic_host_tx_ring *tx_ring)
525aa43c215SJeff Kirsher {
5267777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
527b6b4316cSShahed Shaikh int ret;
5289254b751SSritej Velaga
529b6b4316cSShahed Shaikh ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
530b6b4316cSShahed Shaikh if (ret)
531b6b4316cSShahed Shaikh return;
5327cb03b23SRajesh Borundia
5337e2cf4feSSony Chacko cmd.req.arg[1] = tx_ring->ctx_id;
5347e2cf4feSSony Chacko if (qlcnic_issue_cmd(adapter, &cmd))
535aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
536aa43c215SJeff Kirsher "Failed to destroy tx ctx in firmware\n");
5377e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
538aa43c215SJeff Kirsher }
539aa43c215SJeff Kirsher
540aa43c215SJeff Kirsher int
qlcnic_fw_cmd_set_port(struct qlcnic_adapter * adapter,u32 config)541aa43c215SJeff Kirsher qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
542aa43c215SJeff Kirsher {
5437e2cf4feSSony Chacko int err;
5447777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
5459254b751SSritej Velaga
546b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT);
547b6b4316cSShahed Shaikh if (err)
548b6b4316cSShahed Shaikh return err;
549b6b4316cSShahed Shaikh
5507e2cf4feSSony Chacko cmd.req.arg[1] = config;
5517e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
5527e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
5537e2cf4feSSony Chacko return err;
554aa43c215SJeff Kirsher }
555aa43c215SJeff Kirsher
qlcnic_alloc_hw_resources(struct qlcnic_adapter * adapter)556aa43c215SJeff Kirsher int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
557aa43c215SJeff Kirsher {
558aa43c215SJeff Kirsher void *addr;
5594be41e92SSony Chacko int err, ring;
560aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
561aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
562aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
563aa43c215SJeff Kirsher struct qlcnic_host_tx_ring *tx_ring;
5644be41e92SSony Chacko __le32 *ptr;
565aa43c215SJeff Kirsher
566aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
567aa43c215SJeff Kirsher
568aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
569aa43c215SJeff Kirsher
57034e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
5714be41e92SSony Chacko tx_ring = &adapter->tx_ring[ring];
5724be41e92SSony Chacko ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
5734be41e92SSony Chacko &tx_ring->hw_cons_phys_addr,
5744be41e92SSony Chacko GFP_KERNEL);
575766a957dSChristophe Jaillet if (ptr == NULL) {
576766a957dSChristophe Jaillet err = -ENOMEM;
577766a957dSChristophe Jaillet goto err_out_free;
578766a957dSChristophe Jaillet }
579d0320f75SJoe Perches
5804be41e92SSony Chacko tx_ring->hw_consumer = ptr;
581aa43c215SJeff Kirsher /* cmd desc ring */
582aa43c215SJeff Kirsher addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
5834be41e92SSony Chacko &tx_ring->phys_addr,
5844be41e92SSony Chacko GFP_KERNEL);
585aa43c215SJeff Kirsher if (addr == NULL) {
586aa43c215SJeff Kirsher err = -ENOMEM;
587aa43c215SJeff Kirsher goto err_out_free;
588aa43c215SJeff Kirsher }
589aa43c215SJeff Kirsher
590aa43c215SJeff Kirsher tx_ring->desc_head = addr;
5914be41e92SSony Chacko }
592aa43c215SJeff Kirsher
593aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
594aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
595aa43c215SJeff Kirsher addr = dma_alloc_coherent(&adapter->pdev->dev,
596aa43c215SJeff Kirsher RCV_DESC_RINGSIZE(rds_ring),
597aa43c215SJeff Kirsher &rds_ring->phys_addr, GFP_KERNEL);
598aa43c215SJeff Kirsher if (addr == NULL) {
599aa43c215SJeff Kirsher err = -ENOMEM;
600aa43c215SJeff Kirsher goto err_out_free;
601aa43c215SJeff Kirsher }
602aa43c215SJeff Kirsher rds_ring->desc_head = addr;
603aa43c215SJeff Kirsher
604aa43c215SJeff Kirsher }
605aa43c215SJeff Kirsher
60634e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
607aa43c215SJeff Kirsher sds_ring = &recv_ctx->sds_rings[ring];
608aa43c215SJeff Kirsher
609aa43c215SJeff Kirsher addr = dma_alloc_coherent(&adapter->pdev->dev,
610aa43c215SJeff Kirsher STATUS_DESC_RINGSIZE(sds_ring),
611aa43c215SJeff Kirsher &sds_ring->phys_addr, GFP_KERNEL);
612aa43c215SJeff Kirsher if (addr == NULL) {
613aa43c215SJeff Kirsher err = -ENOMEM;
614aa43c215SJeff Kirsher goto err_out_free;
615aa43c215SJeff Kirsher }
616aa43c215SJeff Kirsher sds_ring->desc_head = addr;
617aa43c215SJeff Kirsher }
618aa43c215SJeff Kirsher
619aa43c215SJeff Kirsher return 0;
620aa43c215SJeff Kirsher
621aa43c215SJeff Kirsher err_out_free:
622aa43c215SJeff Kirsher qlcnic_free_hw_resources(adapter);
623aa43c215SJeff Kirsher return err;
624aa43c215SJeff Kirsher }
625aa43c215SJeff Kirsher
qlcnic_fw_create_ctx(struct qlcnic_adapter * dev)6267e2cf4feSSony Chacko int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
627aa43c215SJeff Kirsher {
6287e2cf4feSSony Chacko int i, err, ring;
629aa43c215SJeff Kirsher
6307e2cf4feSSony Chacko if (dev->flags & QLCNIC_NEED_FLR) {
631*7573099eSDenis Plotnikov err = pci_reset_function(dev->pdev);
632*7573099eSDenis Plotnikov if (err) {
633*7573099eSDenis Plotnikov dev_err(&dev->pdev->dev,
634*7573099eSDenis Plotnikov "Adapter reset failed (%d). Please reboot\n",
635*7573099eSDenis Plotnikov err);
636*7573099eSDenis Plotnikov return err;
637*7573099eSDenis Plotnikov }
6387e2cf4feSSony Chacko dev->flags &= ~QLCNIC_NEED_FLR;
639aa43c215SJeff Kirsher }
640aa43c215SJeff Kirsher
6417dd90cf1SSucheta Chakraborty if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) {
6427dd90cf1SSucheta Chakraborty if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
6437dd90cf1SSucheta Chakraborty err = qlcnic_83xx_config_intrpt(dev, 1);
644aa43c215SJeff Kirsher if (err)
645aa43c215SJeff Kirsher return err;
6467dd90cf1SSucheta Chakraborty }
6477dd90cf1SSucheta Chakraborty }
6487dd90cf1SSucheta Chakraborty
649012ec812SHimanshu Madhani if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) &&
650012ec812SHimanshu Madhani qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test) {
651012ec812SHimanshu Madhani err = qlcnic_82xx_mq_intrpt(dev, 1);
652012ec812SHimanshu Madhani if (err)
653012ec812SHimanshu Madhani return err;
654012ec812SHimanshu Madhani }
655012ec812SHimanshu Madhani
6567dd90cf1SSucheta Chakraborty err = qlcnic_fw_cmd_create_rx_ctx(dev);
6577dd90cf1SSucheta Chakraborty if (err)
6587dd90cf1SSucheta Chakraborty goto err_out;
659aa43c215SJeff Kirsher
66034e8c406SHimanshu Madhani for (ring = 0; ring < dev->drv_tx_rings; ring++) {
6617e2cf4feSSony Chacko err = qlcnic_fw_cmd_create_tx_ctx(dev,
6627e2cf4feSSony Chacko &dev->tx_ring[ring],
6637e2cf4feSSony Chacko ring);
664aa43c215SJeff Kirsher if (err) {
6657cb03b23SRajesh Borundia qlcnic_fw_cmd_del_rx_ctx(dev);
6667e2cf4feSSony Chacko if (ring == 0)
6677dd90cf1SSucheta Chakraborty goto err_out;
6687e2cf4feSSony Chacko
6697e2cf4feSSony Chacko for (i = 0; i < ring; i++)
6707cb03b23SRajesh Borundia qlcnic_fw_cmd_del_tx_ctx(dev, &dev->tx_ring[i]);
6717e2cf4feSSony Chacko
6727dd90cf1SSucheta Chakraborty goto err_out;
673aa43c215SJeff Kirsher }
6747e2cf4feSSony Chacko }
675aa43c215SJeff Kirsher
6767e2cf4feSSony Chacko set_bit(__QLCNIC_FW_ATTACHED, &dev->state);
677012ec812SHimanshu Madhani
678aa43c215SJeff Kirsher return 0;
6797dd90cf1SSucheta Chakraborty
6807dd90cf1SSucheta Chakraborty err_out:
681012ec812SHimanshu Madhani if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) &&
682c2c5e3a0SHimanshu Madhani qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test)
683012ec812SHimanshu Madhani qlcnic_82xx_config_intrpt(dev, 0);
684012ec812SHimanshu Madhani
6857dd90cf1SSucheta Chakraborty if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) {
6867dd90cf1SSucheta Chakraborty if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
6877dd90cf1SSucheta Chakraborty qlcnic_83xx_config_intrpt(dev, 0);
6887dd90cf1SSucheta Chakraborty }
689c2c5e3a0SHimanshu Madhani
6907dd90cf1SSucheta Chakraborty return err;
691aa43c215SJeff Kirsher }
692aa43c215SJeff Kirsher
qlcnic_fw_destroy_ctx(struct qlcnic_adapter * adapter)693aa43c215SJeff Kirsher void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
694aa43c215SJeff Kirsher {
6957e2cf4feSSony Chacko int ring;
6967e2cf4feSSony Chacko
697aa43c215SJeff Kirsher if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
6987cb03b23SRajesh Borundia qlcnic_fw_cmd_del_rx_ctx(adapter);
69934e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_tx_rings; ring++)
7007cb03b23SRajesh Borundia qlcnic_fw_cmd_del_tx_ctx(adapter,
7017e2cf4feSSony Chacko &adapter->tx_ring[ring]);
7027dd90cf1SSucheta Chakraborty
703012ec812SHimanshu Madhani if (qlcnic_82xx_check(adapter) &&
704012ec812SHimanshu Madhani (adapter->flags & QLCNIC_MSIX_ENABLED) &&
705c2c5e3a0SHimanshu Madhani qlcnic_check_multi_tx(adapter) &&
706c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test)
707012ec812SHimanshu Madhani qlcnic_82xx_config_intrpt(adapter, 0);
708012ec812SHimanshu Madhani
7097dd90cf1SSucheta Chakraborty if (qlcnic_83xx_check(adapter) &&
7107dd90cf1SSucheta Chakraborty (adapter->flags & QLCNIC_MSIX_ENABLED)) {
7117dd90cf1SSucheta Chakraborty if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
7127dd90cf1SSucheta Chakraborty qlcnic_83xx_config_intrpt(adapter, 0);
7137dd90cf1SSucheta Chakraborty }
714aa43c215SJeff Kirsher /* Allow dma queues to drain after context reset */
715f57da7a6SShahed Shaikh mdelay(20);
716aa43c215SJeff Kirsher }
717aa43c215SJeff Kirsher }
718aa43c215SJeff Kirsher
qlcnic_free_hw_resources(struct qlcnic_adapter * adapter)719aa43c215SJeff Kirsher void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
720aa43c215SJeff Kirsher {
721aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
722aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
723aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
724aa43c215SJeff Kirsher struct qlcnic_host_tx_ring *tx_ring;
725aa43c215SJeff Kirsher int ring;
726aa43c215SJeff Kirsher
727aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
728aa43c215SJeff Kirsher
72934e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
7304be41e92SSony Chacko tx_ring = &adapter->tx_ring[ring];
731aa43c215SJeff Kirsher if (tx_ring->hw_consumer != NULL) {
7324be41e92SSony Chacko dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
733aa43c215SJeff Kirsher tx_ring->hw_consumer,
734aa43c215SJeff Kirsher tx_ring->hw_cons_phys_addr);
7354be41e92SSony Chacko
736aa43c215SJeff Kirsher tx_ring->hw_consumer = NULL;
737aa43c215SJeff Kirsher }
738aa43c215SJeff Kirsher
739aa43c215SJeff Kirsher if (tx_ring->desc_head != NULL) {
740aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev,
741aa43c215SJeff Kirsher TX_DESC_RINGSIZE(tx_ring),
7424be41e92SSony Chacko tx_ring->desc_head,
7434be41e92SSony Chacko tx_ring->phys_addr);
744aa43c215SJeff Kirsher tx_ring->desc_head = NULL;
745aa43c215SJeff Kirsher }
7464be41e92SSony Chacko }
747aa43c215SJeff Kirsher
748aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
749aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
750aa43c215SJeff Kirsher
751aa43c215SJeff Kirsher if (rds_ring->desc_head != NULL) {
752aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev,
753aa43c215SJeff Kirsher RCV_DESC_RINGSIZE(rds_ring),
754aa43c215SJeff Kirsher rds_ring->desc_head,
755aa43c215SJeff Kirsher rds_ring->phys_addr);
756aa43c215SJeff Kirsher rds_ring->desc_head = NULL;
757aa43c215SJeff Kirsher }
758aa43c215SJeff Kirsher }
759aa43c215SJeff Kirsher
76034e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
761aa43c215SJeff Kirsher sds_ring = &recv_ctx->sds_rings[ring];
762aa43c215SJeff Kirsher
763aa43c215SJeff Kirsher if (sds_ring->desc_head != NULL) {
764aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev,
765aa43c215SJeff Kirsher STATUS_DESC_RINGSIZE(sds_ring),
766aa43c215SJeff Kirsher sds_ring->desc_head,
767aa43c215SJeff Kirsher sds_ring->phys_addr);
768aa43c215SJeff Kirsher sds_ring->desc_head = NULL;
769aa43c215SJeff Kirsher }
770aa43c215SJeff Kirsher }
771aa43c215SJeff Kirsher }
772aa43c215SJeff Kirsher
qlcnic_82xx_config_intrpt(struct qlcnic_adapter * adapter,u8 op_type)773012ec812SHimanshu Madhani int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type)
774012ec812SHimanshu Madhani {
775012ec812SHimanshu Madhani struct qlcnic_hardware_context *ahw = adapter->ahw;
776012ec812SHimanshu Madhani struct net_device *netdev = adapter->netdev;
777012ec812SHimanshu Madhani struct qlcnic_cmd_args cmd;
778012ec812SHimanshu Madhani u32 type, val;
779012ec812SHimanshu Madhani int i, err = 0;
780012ec812SHimanshu Madhani
781012ec812SHimanshu Madhani for (i = 0; i < ahw->num_msix; i++) {
782b77357b6SInsu Yun err = qlcnic_alloc_mbx_args(&cmd, adapter,
783012ec812SHimanshu Madhani QLCNIC_CMD_MQ_TX_CONFIG_INTR);
784b77357b6SInsu Yun if (err)
785b77357b6SInsu Yun return err;
786012ec812SHimanshu Madhani type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
787012ec812SHimanshu Madhani val = type | (ahw->intr_tbl[i].type << 4);
788012ec812SHimanshu Madhani if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
789012ec812SHimanshu Madhani val |= (ahw->intr_tbl[i].id << 16);
790012ec812SHimanshu Madhani cmd.req.arg[1] = val;
791012ec812SHimanshu Madhani err = qlcnic_issue_cmd(adapter, &cmd);
792012ec812SHimanshu Madhani if (err) {
793012ec812SHimanshu Madhani netdev_err(netdev, "Failed to %s interrupts %d\n",
794012ec812SHimanshu Madhani op_type == QLCNIC_INTRPT_ADD ? "Add" :
795012ec812SHimanshu Madhani "Delete", err);
796012ec812SHimanshu Madhani qlcnic_free_mbx_args(&cmd);
797012ec812SHimanshu Madhani return err;
798012ec812SHimanshu Madhani }
799012ec812SHimanshu Madhani val = cmd.rsp.arg[1];
800012ec812SHimanshu Madhani if (LSB(val)) {
801012ec812SHimanshu Madhani netdev_info(netdev,
802012ec812SHimanshu Madhani "failed to configure interrupt for %d\n",
803012ec812SHimanshu Madhani ahw->intr_tbl[i].id);
804012ec812SHimanshu Madhani continue;
805012ec812SHimanshu Madhani }
806012ec812SHimanshu Madhani if (op_type) {
807012ec812SHimanshu Madhani ahw->intr_tbl[i].id = MSW(val);
808012ec812SHimanshu Madhani ahw->intr_tbl[i].enabled = 1;
809012ec812SHimanshu Madhani ahw->intr_tbl[i].src = cmd.rsp.arg[2];
810012ec812SHimanshu Madhani } else {
811012ec812SHimanshu Madhani ahw->intr_tbl[i].id = i;
812012ec812SHimanshu Madhani ahw->intr_tbl[i].enabled = 0;
813012ec812SHimanshu Madhani ahw->intr_tbl[i].src = 0;
814012ec812SHimanshu Madhani }
815012ec812SHimanshu Madhani qlcnic_free_mbx_args(&cmd);
816012ec812SHimanshu Madhani }
817012ec812SHimanshu Madhani
818012ec812SHimanshu Madhani return err;
819012ec812SHimanshu Madhani }
820aa43c215SJeff Kirsher
qlcnic_82xx_get_mac_address(struct qlcnic_adapter * adapter,u8 * mac,u8 function)82107a251c8SShahed Shaikh int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac,
82207a251c8SShahed Shaikh u8 function)
823aa43c215SJeff Kirsher {
8247e2cf4feSSony Chacko int err, i;
8257777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
8267e2cf4feSSony Chacko u32 mac_low, mac_high;
827aa43c215SJeff Kirsher
828b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
829b6b4316cSShahed Shaikh if (err)
830b6b4316cSShahed Shaikh return err;
831b6b4316cSShahed Shaikh
83207a251c8SShahed Shaikh cmd.req.arg[1] = function | BIT_8;
8337e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
834aa43c215SJeff Kirsher
8357e2cf4feSSony Chacko if (err == QLCNIC_RCODE_SUCCESS) {
8367e2cf4feSSony Chacko mac_low = cmd.rsp.arg[1];
8377e2cf4feSSony Chacko mac_high = cmd.rsp.arg[2];
8387e2cf4feSSony Chacko
8397e2cf4feSSony Chacko for (i = 0; i < 2; i++)
8407e2cf4feSSony Chacko mac[i] = (u8) (mac_high >> ((1 - i) * 8));
8417e2cf4feSSony Chacko for (i = 2; i < 6; i++)
8427e2cf4feSSony Chacko mac[i] = (u8) (mac_low >> ((5 - i) * 8));
8437e2cf4feSSony Chacko } else {
844aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
845aa43c215SJeff Kirsher "Failed to get mac address%d\n", err);
846aa43c215SJeff Kirsher err = -EIO;
847aa43c215SJeff Kirsher }
8487e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
849aa43c215SJeff Kirsher return err;
850aa43c215SJeff Kirsher }
851aa43c215SJeff Kirsher
852aa43c215SJeff Kirsher /* Get info of a NIC partition */
qlcnic_82xx_get_nic_info(struct qlcnic_adapter * adapter,struct qlcnic_info * npar_info,u8 func_id)8537e2cf4feSSony Chacko int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
854aa43c215SJeff Kirsher struct qlcnic_info *npar_info, u8 func_id)
855aa43c215SJeff Kirsher {
856aa43c215SJeff Kirsher int err;
857aa43c215SJeff Kirsher dma_addr_t nic_dma_t;
8587e2cf4feSSony Chacko const struct qlcnic_info_le *nic_info;
859aa43c215SJeff Kirsher void *nic_info_addr;
8607777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
86163507592SShahed Shaikh size_t nic_size = sizeof(struct qlcnic_info_le);
862aa43c215SJeff Kirsher
863750afb08SLuis Chamberlain nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
864ede23fa8SJoe Perches &nic_dma_t, GFP_KERNEL);
865aa43c215SJeff Kirsher if (!nic_info_addr)
866aa43c215SJeff Kirsher return -ENOMEM;
867aa43c215SJeff Kirsher
868aa43c215SJeff Kirsher nic_info = nic_info_addr;
869aa43c215SJeff Kirsher
870b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
871b6b4316cSShahed Shaikh if (err)
872b6b4316cSShahed Shaikh goto out_free_dma;
873b6b4316cSShahed Shaikh
8747e2cf4feSSony Chacko cmd.req.arg[1] = MSD(nic_dma_t);
8757e2cf4feSSony Chacko cmd.req.arg[2] = LSD(nic_dma_t);
8767e2cf4feSSony Chacko cmd.req.arg[3] = (func_id << 16 | nic_size);
8777e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
8787e2cf4feSSony Chacko if (err != QLCNIC_RCODE_SUCCESS) {
8797e2cf4feSSony Chacko dev_err(&adapter->pdev->dev,
8807e2cf4feSSony Chacko "Failed to get nic info%d\n", err);
8817e2cf4feSSony Chacko err = -EIO;
8827e2cf4feSSony Chacko } else {
883aa43c215SJeff Kirsher npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
884aa43c215SJeff Kirsher npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
8857e2cf4feSSony Chacko npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
8867e2cf4feSSony Chacko npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
887aa43c215SJeff Kirsher npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
888aa43c215SJeff Kirsher npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
889aa43c215SJeff Kirsher npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
890aa43c215SJeff Kirsher npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
891aa43c215SJeff Kirsher npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
892aa43c215SJeff Kirsher npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
893aa43c215SJeff Kirsher }
894aa43c215SJeff Kirsher
895b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
896b6b4316cSShahed Shaikh out_free_dma:
897aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
898aa43c215SJeff Kirsher nic_dma_t);
8997e2cf4feSSony Chacko
900aa43c215SJeff Kirsher return err;
901aa43c215SJeff Kirsher }
902aa43c215SJeff Kirsher
903aa43c215SJeff Kirsher /* Configure a NIC partition */
qlcnic_82xx_set_nic_info(struct qlcnic_adapter * adapter,struct qlcnic_info * nic)9047e2cf4feSSony Chacko int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
9057e2cf4feSSony Chacko struct qlcnic_info *nic)
906aa43c215SJeff Kirsher {
907aa43c215SJeff Kirsher int err = -EIO;
908aa43c215SJeff Kirsher dma_addr_t nic_dma_t;
909aa43c215SJeff Kirsher void *nic_info_addr;
9107777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
91163507592SShahed Shaikh struct qlcnic_info_le *nic_info;
91263507592SShahed Shaikh size_t nic_size = sizeof(struct qlcnic_info_le);
913aa43c215SJeff Kirsher
91479788450SSony Chacko if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
915aa43c215SJeff Kirsher return err;
916aa43c215SJeff Kirsher
917750afb08SLuis Chamberlain nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
918ede23fa8SJoe Perches &nic_dma_t, GFP_KERNEL);
919aa43c215SJeff Kirsher if (!nic_info_addr)
920aa43c215SJeff Kirsher return -ENOMEM;
921aa43c215SJeff Kirsher
922aa43c215SJeff Kirsher nic_info = nic_info_addr;
923aa43c215SJeff Kirsher
924aa43c215SJeff Kirsher nic_info->pci_func = cpu_to_le16(nic->pci_func);
925aa43c215SJeff Kirsher nic_info->op_mode = cpu_to_le16(nic->op_mode);
926aa43c215SJeff Kirsher nic_info->phys_port = cpu_to_le16(nic->phys_port);
927aa43c215SJeff Kirsher nic_info->switch_mode = cpu_to_le16(nic->switch_mode);
928aa43c215SJeff Kirsher nic_info->capabilities = cpu_to_le32(nic->capabilities);
929aa43c215SJeff Kirsher nic_info->max_mac_filters = nic->max_mac_filters;
930aa43c215SJeff Kirsher nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques);
931aa43c215SJeff Kirsher nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques);
932aa43c215SJeff Kirsher nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
933aa43c215SJeff Kirsher nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
934aa43c215SJeff Kirsher
935b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
936b6b4316cSShahed Shaikh if (err)
937b6b4316cSShahed Shaikh goto out_free_dma;
938b6b4316cSShahed Shaikh
9397e2cf4feSSony Chacko cmd.req.arg[1] = MSD(nic_dma_t);
9407e2cf4feSSony Chacko cmd.req.arg[2] = LSD(nic_dma_t);
9417e2cf4feSSony Chacko cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
9427e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
943aa43c215SJeff Kirsher
944aa43c215SJeff Kirsher if (err != QLCNIC_RCODE_SUCCESS) {
945aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
946aa43c215SJeff Kirsher "Failed to set nic info%d\n", err);
947aa43c215SJeff Kirsher err = -EIO;
948aa43c215SJeff Kirsher }
949aa43c215SJeff Kirsher
950b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
951b6b4316cSShahed Shaikh out_free_dma:
952aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
953aa43c215SJeff Kirsher nic_dma_t);
9547e2cf4feSSony Chacko
955aa43c215SJeff Kirsher return err;
956aa43c215SJeff Kirsher }
957aa43c215SJeff Kirsher
958aa43c215SJeff Kirsher /* Get PCI Info of a partition */
qlcnic_82xx_get_pci_info(struct qlcnic_adapter * adapter,struct qlcnic_pci_info * pci_info)9597e2cf4feSSony Chacko int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
960aa43c215SJeff Kirsher struct qlcnic_pci_info *pci_info)
961aa43c215SJeff Kirsher {
9622f514c52SJitendra Kalsaria struct qlcnic_hardware_context *ahw = adapter->ahw;
9632f514c52SJitendra Kalsaria size_t npar_size = sizeof(struct qlcnic_pci_info_le);
9642f514c52SJitendra Kalsaria size_t pci_size = npar_size * ahw->max_vnic_func;
9652f514c52SJitendra Kalsaria u16 nic = 0, fcoe = 0, iscsi = 0;
9662f514c52SJitendra Kalsaria struct qlcnic_pci_info_le *npar;
9677777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
968aa43c215SJeff Kirsher dma_addr_t pci_info_dma_t;
969aa43c215SJeff Kirsher void *pci_info_addr;
9702f514c52SJitendra Kalsaria int err = 0, i;
971aa43c215SJeff Kirsher
972750afb08SLuis Chamberlain pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
973ede23fa8SJoe Perches &pci_info_dma_t, GFP_KERNEL);
974aa43c215SJeff Kirsher if (!pci_info_addr)
975aa43c215SJeff Kirsher return -ENOMEM;
976aa43c215SJeff Kirsher
977aa43c215SJeff Kirsher npar = pci_info_addr;
978b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
979b6b4316cSShahed Shaikh if (err)
980b6b4316cSShahed Shaikh goto out_free_dma;
981b6b4316cSShahed Shaikh
9827e2cf4feSSony Chacko cmd.req.arg[1] = MSD(pci_info_dma_t);
9837e2cf4feSSony Chacko cmd.req.arg[2] = LSD(pci_info_dma_t);
9847e2cf4feSSony Chacko cmd.req.arg[3] = pci_size;
9857e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
986aa43c215SJeff Kirsher
9872f514c52SJitendra Kalsaria ahw->total_nic_func = 0;
988aa43c215SJeff Kirsher if (err == QLCNIC_RCODE_SUCCESS) {
9892f514c52SJitendra Kalsaria for (i = 0; i < ahw->max_vnic_func; i++, npar++, pci_info++) {
990aa43c215SJeff Kirsher pci_info->id = le16_to_cpu(npar->id);
991aa43c215SJeff Kirsher pci_info->active = le16_to_cpu(npar->active);
9922f514c52SJitendra Kalsaria if (!pci_info->active)
9932f514c52SJitendra Kalsaria continue;
994aa43c215SJeff Kirsher pci_info->type = le16_to_cpu(npar->type);
9952f514c52SJitendra Kalsaria err = qlcnic_get_pci_func_type(adapter, pci_info->type,
9962f514c52SJitendra Kalsaria &nic, &fcoe, &iscsi);
997aa43c215SJeff Kirsher pci_info->default_port =
998aa43c215SJeff Kirsher le16_to_cpu(npar->default_port);
999aa43c215SJeff Kirsher pci_info->tx_min_bw =
1000aa43c215SJeff Kirsher le16_to_cpu(npar->tx_min_bw);
1001aa43c215SJeff Kirsher pci_info->tx_max_bw =
1002aa43c215SJeff Kirsher le16_to_cpu(npar->tx_max_bw);
1003aa43c215SJeff Kirsher memcpy(pci_info->mac, npar->mac, ETH_ALEN);
1004aa43c215SJeff Kirsher }
1005aa43c215SJeff Kirsher } else {
1006aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
1007aa43c215SJeff Kirsher "Failed to get PCI Info%d\n", err);
1008aa43c215SJeff Kirsher err = -EIO;
1009aa43c215SJeff Kirsher }
1010aa43c215SJeff Kirsher
10112f514c52SJitendra Kalsaria ahw->total_nic_func = nic;
10122f514c52SJitendra Kalsaria ahw->total_pci_func = nic + fcoe + iscsi;
10132f514c52SJitendra Kalsaria if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
10142f514c52SJitendra Kalsaria dev_err(&adapter->pdev->dev,
10152f514c52SJitendra Kalsaria "%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
10162f514c52SJitendra Kalsaria __func__, ahw->total_nic_func, ahw->total_pci_func);
10172f514c52SJitendra Kalsaria err = -EIO;
10182f514c52SJitendra Kalsaria }
1019b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
1020b6b4316cSShahed Shaikh out_free_dma:
1021aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
1022aa43c215SJeff Kirsher pci_info_dma_t);
10237e2cf4feSSony Chacko
1024aa43c215SJeff Kirsher return err;
1025aa43c215SJeff Kirsher }
1026aa43c215SJeff Kirsher
1027aa43c215SJeff Kirsher /* Configure eSwitch for port mirroring */
qlcnic_config_port_mirroring(struct qlcnic_adapter * adapter,u8 id,u8 enable_mirroring,u8 pci_func)1028aa43c215SJeff Kirsher int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
1029aa43c215SJeff Kirsher u8 enable_mirroring, u8 pci_func)
1030aa43c215SJeff Kirsher {
1031ee9e8b6cSManish Chopra struct device *dev = &adapter->pdev->dev;
1032ee9e8b6cSManish Chopra struct qlcnic_cmd_args cmd;
1033aa43c215SJeff Kirsher int err = -EIO;
1034aa43c215SJeff Kirsher u32 arg1;
1035aa43c215SJeff Kirsher
103679788450SSony Chacko if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
1037c65762fcSSucheta Chakraborty !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) {
1038c65762fcSSucheta Chakraborty dev_err(&adapter->pdev->dev, "%s: Not a management function\n",
1039c65762fcSSucheta Chakraborty __func__);
1040aa43c215SJeff Kirsher return err;
1041c65762fcSSucheta Chakraborty }
1042aa43c215SJeff Kirsher
1043aa43c215SJeff Kirsher arg1 = id | (enable_mirroring ? BIT_4 : 0);
1044aa43c215SJeff Kirsher arg1 |= pci_func << 8;
1045aa43c215SJeff Kirsher
1046b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter,
1047b6b4316cSShahed Shaikh QLCNIC_CMD_SET_PORTMIRRORING);
1048b6b4316cSShahed Shaikh if (err)
1049b6b4316cSShahed Shaikh return err;
1050b6b4316cSShahed Shaikh
10517e2cf4feSSony Chacko cmd.req.arg[1] = arg1;
10527e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
1053aa43c215SJeff Kirsher
10547e2cf4feSSony Chacko if (err != QLCNIC_RCODE_SUCCESS)
1055ee9e8b6cSManish Chopra dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n",
1056aa43c215SJeff Kirsher pci_func, id);
10577e2cf4feSSony Chacko else
1058ee9e8b6cSManish Chopra dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n",
1059ee9e8b6cSManish Chopra pci_func, id);
10607e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
1061aa43c215SJeff Kirsher
1062aa43c215SJeff Kirsher return err;
1063aa43c215SJeff Kirsher }
1064aa43c215SJeff Kirsher
qlcnic_get_port_stats(struct qlcnic_adapter * adapter,const u8 func,const u8 rx_tx,struct __qlcnic_esw_statistics * esw_stats)1065aa43c215SJeff Kirsher int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
1066aa43c215SJeff Kirsher const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
1067aa43c215SJeff Kirsher
106863507592SShahed Shaikh size_t stats_size = sizeof(struct qlcnic_esw_stats_le);
106963507592SShahed Shaikh struct qlcnic_esw_stats_le *stats;
1070aa43c215SJeff Kirsher dma_addr_t stats_dma_t;
1071aa43c215SJeff Kirsher void *stats_addr;
1072aa43c215SJeff Kirsher u32 arg1;
10737777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
1074aa43c215SJeff Kirsher int err;
1075aa43c215SJeff Kirsher
1076aa43c215SJeff Kirsher if (esw_stats == NULL)
1077aa43c215SJeff Kirsher return -ENOMEM;
1078aa43c215SJeff Kirsher
107979788450SSony Chacko if ((adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) &&
108079788450SSony Chacko (func != adapter->ahw->pci_func)) {
1081aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
1082aa43c215SJeff Kirsher "Not privilege to query stats for func=%d", func);
1083aa43c215SJeff Kirsher return -EIO;
1084aa43c215SJeff Kirsher }
1085aa43c215SJeff Kirsher
1086750afb08SLuis Chamberlain stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
1087ede23fa8SJoe Perches &stats_dma_t, GFP_KERNEL);
1088d0320f75SJoe Perches if (!stats_addr)
1089aa43c215SJeff Kirsher return -ENOMEM;
1090d0320f75SJoe Perches
1091aa43c215SJeff Kirsher arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
1092aa43c215SJeff Kirsher arg1 |= rx_tx << 15 | stats_size << 16;
1093aa43c215SJeff Kirsher
1094b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter,
1095b6b4316cSShahed Shaikh QLCNIC_CMD_GET_ESWITCH_STATS);
1096b6b4316cSShahed Shaikh if (err)
1097b6b4316cSShahed Shaikh goto out_free_dma;
1098b6b4316cSShahed Shaikh
10997e2cf4feSSony Chacko cmd.req.arg[1] = arg1;
11007e2cf4feSSony Chacko cmd.req.arg[2] = MSD(stats_dma_t);
11017e2cf4feSSony Chacko cmd.req.arg[3] = LSD(stats_dma_t);
11027e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
1103aa43c215SJeff Kirsher
1104aa43c215SJeff Kirsher if (!err) {
1105aa43c215SJeff Kirsher stats = stats_addr;
1106aa43c215SJeff Kirsher esw_stats->context_id = le16_to_cpu(stats->context_id);
1107aa43c215SJeff Kirsher esw_stats->version = le16_to_cpu(stats->version);
1108aa43c215SJeff Kirsher esw_stats->size = le16_to_cpu(stats->size);
1109aa43c215SJeff Kirsher esw_stats->multicast_frames =
1110aa43c215SJeff Kirsher le64_to_cpu(stats->multicast_frames);
1111aa43c215SJeff Kirsher esw_stats->broadcast_frames =
1112aa43c215SJeff Kirsher le64_to_cpu(stats->broadcast_frames);
1113aa43c215SJeff Kirsher esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
1114aa43c215SJeff Kirsher esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
1115aa43c215SJeff Kirsher esw_stats->local_frames = le64_to_cpu(stats->local_frames);
1116aa43c215SJeff Kirsher esw_stats->errors = le64_to_cpu(stats->errors);
1117aa43c215SJeff Kirsher esw_stats->numbytes = le64_to_cpu(stats->numbytes);
1118aa43c215SJeff Kirsher }
1119aa43c215SJeff Kirsher
1120b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
1121b6b4316cSShahed Shaikh out_free_dma:
1122aa43c215SJeff Kirsher dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
1123aa43c215SJeff Kirsher stats_dma_t);
11247e2cf4feSSony Chacko
1125aa43c215SJeff Kirsher return err;
1126aa43c215SJeff Kirsher }
1127aa43c215SJeff Kirsher
112854a8997cSJitendra Kalsaria /* This routine will retrieve the MAC statistics from firmware */
qlcnic_get_mac_stats(struct qlcnic_adapter * adapter,struct qlcnic_mac_statistics * mac_stats)112954a8997cSJitendra Kalsaria int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
113054a8997cSJitendra Kalsaria struct qlcnic_mac_statistics *mac_stats)
113154a8997cSJitendra Kalsaria {
113263507592SShahed Shaikh struct qlcnic_mac_statistics_le *stats;
113354a8997cSJitendra Kalsaria struct qlcnic_cmd_args cmd;
113463507592SShahed Shaikh size_t stats_size = sizeof(struct qlcnic_mac_statistics_le);
113554a8997cSJitendra Kalsaria dma_addr_t stats_dma_t;
113654a8997cSJitendra Kalsaria void *stats_addr;
113754a8997cSJitendra Kalsaria int err;
113854a8997cSJitendra Kalsaria
11397e2cf4feSSony Chacko if (mac_stats == NULL)
11407e2cf4feSSony Chacko return -ENOMEM;
11417e2cf4feSSony Chacko
1142750afb08SLuis Chamberlain stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
1143ede23fa8SJoe Perches &stats_dma_t, GFP_KERNEL);
1144d0320f75SJoe Perches if (!stats_addr)
114554a8997cSJitendra Kalsaria return -ENOMEM;
1146d0320f75SJoe Perches
1147b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
1148b6b4316cSShahed Shaikh if (err)
1149b6b4316cSShahed Shaikh goto out_free_dma;
1150b6b4316cSShahed Shaikh
11517e2cf4feSSony Chacko cmd.req.arg[1] = stats_size << 16;
11527e2cf4feSSony Chacko cmd.req.arg[2] = MSD(stats_dma_t);
11537e2cf4feSSony Chacko cmd.req.arg[3] = LSD(stats_dma_t);
11547e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
115554a8997cSJitendra Kalsaria if (!err) {
115654a8997cSJitendra Kalsaria stats = stats_addr;
115754a8997cSJitendra Kalsaria mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
115854a8997cSJitendra Kalsaria mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
115954a8997cSJitendra Kalsaria mac_stats->mac_tx_mcast_pkts =
116054a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_tx_mcast_pkts);
116154a8997cSJitendra Kalsaria mac_stats->mac_tx_bcast_pkts =
116254a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_tx_bcast_pkts);
116354a8997cSJitendra Kalsaria mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
116454a8997cSJitendra Kalsaria mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
116554a8997cSJitendra Kalsaria mac_stats->mac_rx_mcast_pkts =
116654a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_rx_mcast_pkts);
116754a8997cSJitendra Kalsaria mac_stats->mac_rx_length_error =
116854a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_rx_length_error);
116954a8997cSJitendra Kalsaria mac_stats->mac_rx_length_small =
117054a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_rx_length_small);
117154a8997cSJitendra Kalsaria mac_stats->mac_rx_length_large =
117254a8997cSJitendra Kalsaria le64_to_cpu(stats->mac_rx_length_large);
117354a8997cSJitendra Kalsaria mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
117454a8997cSJitendra Kalsaria mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
117554a8997cSJitendra Kalsaria mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
11767e2cf4feSSony Chacko } else {
11777e2cf4feSSony Chacko dev_err(&adapter->pdev->dev,
11787e2cf4feSSony Chacko "%s: Get mac stats failed, err=%d.\n", __func__, err);
117954a8997cSJitendra Kalsaria }
118054a8997cSJitendra Kalsaria
1181b6b4316cSShahed Shaikh qlcnic_free_mbx_args(&cmd);
1182b6b4316cSShahed Shaikh
1183b6b4316cSShahed Shaikh out_free_dma:
118454a8997cSJitendra Kalsaria dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
118554a8997cSJitendra Kalsaria stats_dma_t);
11867e2cf4feSSony Chacko
118754a8997cSJitendra Kalsaria return err;
118854a8997cSJitendra Kalsaria }
118954a8997cSJitendra Kalsaria
qlcnic_get_eswitch_stats(struct qlcnic_adapter * adapter,const u8 eswitch,const u8 rx_tx,struct __qlcnic_esw_statistics * esw_stats)1190aa43c215SJeff Kirsher int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
1191aa43c215SJeff Kirsher const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
1192aa43c215SJeff Kirsher
1193aa43c215SJeff Kirsher struct __qlcnic_esw_statistics port_stats;
1194aa43c215SJeff Kirsher u8 i;
1195aa43c215SJeff Kirsher int ret = -EIO;
1196aa43c215SJeff Kirsher
1197aa43c215SJeff Kirsher if (esw_stats == NULL)
1198aa43c215SJeff Kirsher return -ENOMEM;
119979788450SSony Chacko if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
1200aa43c215SJeff Kirsher return -EIO;
1201aa43c215SJeff Kirsher if (adapter->npars == NULL)
1202aa43c215SJeff Kirsher return -EIO;
1203aa43c215SJeff Kirsher
1204aa43c215SJeff Kirsher memset(esw_stats, 0, sizeof(u64));
120554a8997cSJitendra Kalsaria esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
120654a8997cSJitendra Kalsaria esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
120754a8997cSJitendra Kalsaria esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
120854a8997cSJitendra Kalsaria esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
120954a8997cSJitendra Kalsaria esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
121054a8997cSJitendra Kalsaria esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
121154a8997cSJitendra Kalsaria esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
1212aa43c215SJeff Kirsher esw_stats->context_id = eswitch;
1213aa43c215SJeff Kirsher
12142f514c52SJitendra Kalsaria for (i = 0; i < adapter->ahw->total_nic_func; i++) {
1215aa43c215SJeff Kirsher if (adapter->npars[i].phy_port != eswitch)
1216aa43c215SJeff Kirsher continue;
1217aa43c215SJeff Kirsher
1218aa43c215SJeff Kirsher memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
1219bff57d8eSSony Chacko if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func,
1220bff57d8eSSony Chacko rx_tx, &port_stats))
1221aa43c215SJeff Kirsher continue;
1222aa43c215SJeff Kirsher
1223aa43c215SJeff Kirsher esw_stats->size = port_stats.size;
1224aa43c215SJeff Kirsher esw_stats->version = port_stats.version;
1225aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
1226aa43c215SJeff Kirsher port_stats.unicast_frames);
1227aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
1228aa43c215SJeff Kirsher port_stats.multicast_frames);
1229aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
1230aa43c215SJeff Kirsher port_stats.broadcast_frames);
1231aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
1232aa43c215SJeff Kirsher port_stats.dropped_frames);
1233aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->errors,
1234aa43c215SJeff Kirsher port_stats.errors);
1235aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
1236aa43c215SJeff Kirsher port_stats.local_frames);
1237aa43c215SJeff Kirsher QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
1238aa43c215SJeff Kirsher port_stats.numbytes);
1239aa43c215SJeff Kirsher ret = 0;
1240aa43c215SJeff Kirsher }
1241aa43c215SJeff Kirsher return ret;
1242aa43c215SJeff Kirsher }
1243aa43c215SJeff Kirsher
qlcnic_clear_esw_stats(struct qlcnic_adapter * adapter,const u8 func_esw,const u8 port,const u8 rx_tx)1244aa43c215SJeff Kirsher int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
1245aa43c215SJeff Kirsher const u8 port, const u8 rx_tx)
1246aa43c215SJeff Kirsher {
12472f514c52SJitendra Kalsaria struct qlcnic_hardware_context *ahw = adapter->ahw;
12482f514c52SJitendra Kalsaria struct qlcnic_cmd_args cmd;
12497e2cf4feSSony Chacko int err;
1250aa43c215SJeff Kirsher u32 arg1;
1251aa43c215SJeff Kirsher
12522f514c52SJitendra Kalsaria if (ahw->op_mode != QLCNIC_MGMT_FUNC)
1253aa43c215SJeff Kirsher return -EIO;
1254aa43c215SJeff Kirsher
1255aa43c215SJeff Kirsher if (func_esw == QLCNIC_STATS_PORT) {
12562f514c52SJitendra Kalsaria if (port >= ahw->max_vnic_func)
1257aa43c215SJeff Kirsher goto err_ret;
1258aa43c215SJeff Kirsher } else if (func_esw == QLCNIC_STATS_ESWITCH) {
1259aa43c215SJeff Kirsher if (port >= QLCNIC_NIU_MAX_XG_PORTS)
1260aa43c215SJeff Kirsher goto err_ret;
1261aa43c215SJeff Kirsher } else {
1262aa43c215SJeff Kirsher goto err_ret;
1263aa43c215SJeff Kirsher }
1264aa43c215SJeff Kirsher
1265aa43c215SJeff Kirsher if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
1266aa43c215SJeff Kirsher goto err_ret;
1267aa43c215SJeff Kirsher
1268aa43c215SJeff Kirsher arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
1269aa43c215SJeff Kirsher arg1 |= BIT_14 | rx_tx << 15;
1270aa43c215SJeff Kirsher
1271b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter,
1272b6b4316cSShahed Shaikh QLCNIC_CMD_GET_ESWITCH_STATS);
1273b6b4316cSShahed Shaikh if (err)
1274b6b4316cSShahed Shaikh return err;
1275b6b4316cSShahed Shaikh
12767e2cf4feSSony Chacko cmd.req.arg[1] = arg1;
12777e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
12787e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
12797e2cf4feSSony Chacko return err;
1280aa43c215SJeff Kirsher
1281aa43c215SJeff Kirsher err_ret:
12827e2cf4feSSony Chacko dev_err(&adapter->pdev->dev,
12837e2cf4feSSony Chacko "Invalid args func_esw %d port %d rx_ctx %d\n",
12847e2cf4feSSony Chacko func_esw, port, rx_tx);
1285aa43c215SJeff Kirsher return -EIO;
1286aa43c215SJeff Kirsher }
1287aa43c215SJeff Kirsher
__qlcnic_get_eswitch_port_config(struct qlcnic_adapter * adapter,u32 * arg1,u32 * arg2)1288ee9e8b6cSManish Chopra static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
1289aa43c215SJeff Kirsher u32 *arg1, u32 *arg2)
1290aa43c215SJeff Kirsher {
1291ee9e8b6cSManish Chopra struct device *dev = &adapter->pdev->dev;
12927777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
1293ee9e8b6cSManish Chopra u8 pci_func = *arg1 >> 8;
1294b6b4316cSShahed Shaikh int err;
12957777de9aSAnirban Chakraborty
1296b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter,
12977e2cf4feSSony Chacko QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
1298b6b4316cSShahed Shaikh if (err)
1299b6b4316cSShahed Shaikh return err;
1300b6b4316cSShahed Shaikh
13017e2cf4feSSony Chacko cmd.req.arg[1] = *arg1;
13027e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
13037e2cf4feSSony Chacko *arg1 = cmd.rsp.arg[1];
13047e2cf4feSSony Chacko *arg2 = cmd.rsp.arg[2];
13057e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
1306aa43c215SJeff Kirsher
13077e2cf4feSSony Chacko if (err == QLCNIC_RCODE_SUCCESS)
1308ee9e8b6cSManish Chopra dev_info(dev, "Get eSwitch port config for vNIC function %d\n",
1309ee9e8b6cSManish Chopra pci_func);
13107e2cf4feSSony Chacko else
1311ee9e8b6cSManish Chopra dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n",
1312aa43c215SJeff Kirsher pci_func);
1313aa43c215SJeff Kirsher return err;
1314aa43c215SJeff Kirsher }
1315aa43c215SJeff Kirsher /* Configure eSwitch port
1316aa43c215SJeff Kirsher op_mode = 0 for setting default port behavior
1317aa43c215SJeff Kirsher op_mode = 1 for setting vlan id
1318aa43c215SJeff Kirsher op_mode = 2 for deleting vlan id
1319aa43c215SJeff Kirsher op_type = 0 for vlan_id
1320aa43c215SJeff Kirsher op_type = 1 for port vlan_id
1321aa43c215SJeff Kirsher */
qlcnic_config_switch_port(struct qlcnic_adapter * adapter,struct qlcnic_esw_func_cfg * esw_cfg)1322aa43c215SJeff Kirsher int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
1323aa43c215SJeff Kirsher struct qlcnic_esw_func_cfg *esw_cfg)
1324aa43c215SJeff Kirsher {
1325ee9e8b6cSManish Chopra struct device *dev = &adapter->pdev->dev;
1326ee9e8b6cSManish Chopra struct qlcnic_cmd_args cmd;
1327bff57d8eSSony Chacko int err = -EIO, index;
1328aa43c215SJeff Kirsher u32 arg1, arg2 = 0;
1329aa43c215SJeff Kirsher u8 pci_func;
1330aa43c215SJeff Kirsher
1331c65762fcSSucheta Chakraborty if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
1332c65762fcSSucheta Chakraborty dev_err(&adapter->pdev->dev, "%s: Not a management function\n",
1333c65762fcSSucheta Chakraborty __func__);
1334aa43c215SJeff Kirsher return err;
1335c65762fcSSucheta Chakraborty }
1336c65762fcSSucheta Chakraborty
1337aa43c215SJeff Kirsher pci_func = esw_cfg->pci_func;
1338bff57d8eSSony Chacko index = qlcnic_is_valid_nic_func(adapter, pci_func);
1339bff57d8eSSony Chacko if (index < 0)
1340bff57d8eSSony Chacko return err;
1341bff57d8eSSony Chacko arg1 = (adapter->npars[index].phy_port & BIT_0);
1342aa43c215SJeff Kirsher arg1 |= (pci_func << 8);
1343aa43c215SJeff Kirsher
1344aa43c215SJeff Kirsher if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
1345aa43c215SJeff Kirsher return err;
1346aa43c215SJeff Kirsher arg1 &= ~(0x0ff << 8);
1347aa43c215SJeff Kirsher arg1 |= (pci_func << 8);
1348aa43c215SJeff Kirsher arg1 &= ~(BIT_2 | BIT_3);
1349aa43c215SJeff Kirsher switch (esw_cfg->op_mode) {
1350aa43c215SJeff Kirsher case QLCNIC_PORT_DEFAULTS:
1351aa43c215SJeff Kirsher arg1 |= (BIT_4 | BIT_6 | BIT_7);
1352aa43c215SJeff Kirsher arg2 |= (BIT_0 | BIT_1);
135379788450SSony Chacko if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
1354aa43c215SJeff Kirsher arg2 |= (BIT_2 | BIT_3);
1355aa43c215SJeff Kirsher if (!(esw_cfg->discard_tagged))
1356aa43c215SJeff Kirsher arg1 &= ~BIT_4;
1357aa43c215SJeff Kirsher if (!(esw_cfg->promisc_mode))
1358aa43c215SJeff Kirsher arg1 &= ~BIT_6;
1359aa43c215SJeff Kirsher if (!(esw_cfg->mac_override))
1360aa43c215SJeff Kirsher arg1 &= ~BIT_7;
1361aa43c215SJeff Kirsher if (!(esw_cfg->mac_anti_spoof))
1362aa43c215SJeff Kirsher arg2 &= ~BIT_0;
1363aa43c215SJeff Kirsher if (!(esw_cfg->offload_flags & BIT_0))
1364aa43c215SJeff Kirsher arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
1365aa43c215SJeff Kirsher if (!(esw_cfg->offload_flags & BIT_1))
1366aa43c215SJeff Kirsher arg2 &= ~BIT_2;
1367aa43c215SJeff Kirsher if (!(esw_cfg->offload_flags & BIT_2))
1368aa43c215SJeff Kirsher arg2 &= ~BIT_3;
1369aa43c215SJeff Kirsher break;
1370aa43c215SJeff Kirsher case QLCNIC_ADD_VLAN:
1371a78b6da8SJitendra Kalsaria arg1 &= ~(0x0ffff << 16);
1372aa43c215SJeff Kirsher arg1 |= (BIT_2 | BIT_5);
1373aa43c215SJeff Kirsher arg1 |= (esw_cfg->vlan_id << 16);
1374aa43c215SJeff Kirsher break;
1375aa43c215SJeff Kirsher case QLCNIC_DEL_VLAN:
1376aa43c215SJeff Kirsher arg1 |= (BIT_3 | BIT_5);
1377aa43c215SJeff Kirsher arg1 &= ~(0x0ffff << 16);
1378aa43c215SJeff Kirsher break;
1379aa43c215SJeff Kirsher default:
1380c65762fcSSucheta Chakraborty dev_err(&adapter->pdev->dev, "%s: Invalid opmode 0x%x\n",
1381c65762fcSSucheta Chakraborty __func__, esw_cfg->op_mode);
1382aa43c215SJeff Kirsher return err;
1383aa43c215SJeff Kirsher }
1384aa43c215SJeff Kirsher
1385b6b4316cSShahed Shaikh err = qlcnic_alloc_mbx_args(&cmd, adapter,
1386b6b4316cSShahed Shaikh QLCNIC_CMD_CONFIGURE_ESWITCH);
1387b6b4316cSShahed Shaikh if (err)
1388b6b4316cSShahed Shaikh return err;
1389b6b4316cSShahed Shaikh
13907e2cf4feSSony Chacko cmd.req.arg[1] = arg1;
13917e2cf4feSSony Chacko cmd.req.arg[2] = arg2;
13927e2cf4feSSony Chacko err = qlcnic_issue_cmd(adapter, &cmd);
13937e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
1394aa43c215SJeff Kirsher
13957e2cf4feSSony Chacko if (err != QLCNIC_RCODE_SUCCESS)
1396ee9e8b6cSManish Chopra dev_err(dev, "Failed to configure eswitch for vNIC function %d\n",
1397ee9e8b6cSManish Chopra pci_func);
13987e2cf4feSSony Chacko else
1399ee9e8b6cSManish Chopra dev_info(dev, "Configured eSwitch for vNIC function %d\n",
1400ee9e8b6cSManish Chopra pci_func);
1401aa43c215SJeff Kirsher
1402aa43c215SJeff Kirsher return err;
1403aa43c215SJeff Kirsher }
1404aa43c215SJeff Kirsher
1405aa43c215SJeff Kirsher int
qlcnic_get_eswitch_port_config(struct qlcnic_adapter * adapter,struct qlcnic_esw_func_cfg * esw_cfg)1406aa43c215SJeff Kirsher qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
1407aa43c215SJeff Kirsher struct qlcnic_esw_func_cfg *esw_cfg)
1408aa43c215SJeff Kirsher {
1409aa43c215SJeff Kirsher u32 arg1, arg2;
1410bff57d8eSSony Chacko int index;
1411aa43c215SJeff Kirsher u8 phy_port;
1412bff57d8eSSony Chacko
1413bff57d8eSSony Chacko if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
1414bff57d8eSSony Chacko index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func);
1415bff57d8eSSony Chacko if (index < 0)
1416bff57d8eSSony Chacko return -EIO;
1417bff57d8eSSony Chacko phy_port = adapter->npars[index].phy_port;
1418bff57d8eSSony Chacko } else {
141979788450SSony Chacko phy_port = adapter->ahw->physical_port;
1420bff57d8eSSony Chacko }
1421aa43c215SJeff Kirsher arg1 = phy_port;
1422aa43c215SJeff Kirsher arg1 |= (esw_cfg->pci_func << 8);
1423aa43c215SJeff Kirsher if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
1424aa43c215SJeff Kirsher return -EIO;
1425aa43c215SJeff Kirsher
1426aa43c215SJeff Kirsher esw_cfg->discard_tagged = !!(arg1 & BIT_4);
1427aa43c215SJeff Kirsher esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
1428aa43c215SJeff Kirsher esw_cfg->promisc_mode = !!(arg1 & BIT_6);
1429aa43c215SJeff Kirsher esw_cfg->mac_override = !!(arg1 & BIT_7);
1430aa43c215SJeff Kirsher esw_cfg->vlan_id = LSW(arg1 >> 16);
1431aa43c215SJeff Kirsher esw_cfg->mac_anti_spoof = (arg2 & 0x1);
1432aa43c215SJeff Kirsher esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
1433aa43c215SJeff Kirsher
1434aa43c215SJeff Kirsher return 0;
1435aa43c215SJeff Kirsher }
1436