blob: 2b68779a176f1b8e66aa6d68248e9256b828895c [file] [log] [blame]
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001/*
Sritej Velaga40839129f2010-12-02 20:41:56 +00002 * QLogic qlcnic NIC Driver
Jitendra Kalsaria577ae392013-02-04 12:33:07 +00003 * Copyright (c) 2009-2013 QLogic Corporation
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00004 *
Sritej Velaga40839129f2010-12-02 20:41:56 +00005 * See LICENSE.qlcnic for copyright and licensing details.
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00006 */
7
8#include "qlcnic.h"
9
Sony Chacko7e2cf4f2013-01-01 03:20:17 +000010static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
11 {QLCNIC_CMD_CREATE_RX_CTX, 4, 1},
12 {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
13 {QLCNIC_CMD_CREATE_TX_CTX, 4, 1},
14 {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
15 {QLCNIC_CMD_INTRPT_TEST, 4, 1},
16 {QLCNIC_CMD_SET_MTU, 4, 1},
17 {QLCNIC_CMD_READ_PHY, 4, 2},
18 {QLCNIC_CMD_WRITE_PHY, 5, 1},
19 {QLCNIC_CMD_READ_HW_REG, 4, 1},
20 {QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
21 {QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
22 {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
23 {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
24 {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
25 {QLCNIC_CMD_GET_PCI_INFO, 4, 1},
26 {QLCNIC_CMD_GET_NIC_INFO, 4, 1},
27 {QLCNIC_CMD_SET_NIC_INFO, 4, 1},
28 {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
29 {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
30 {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
31 {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
32 {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
33 {QLCNIC_CMD_GET_MAC_STATS, 4, 1},
34 {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
35 {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
36 {QLCNIC_CMD_CONFIG_PORT, 4, 1},
37 {QLCNIC_CMD_TEMP_SIZE, 4, 4},
38 {QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
Pratik Pujar8af3f332013-06-22 04:12:05 -040039 {QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1},
Himanshu Madhani487042a2013-05-23 21:04:33 +000040 {QLCNIC_CMD_GET_LED_STATUS, 4, 2},
Himanshu Madhani012ec812013-08-21 11:24:10 -040041 {QLCNIC_CMD_MQ_TX_CONFIG_INTR, 2, 3},
Sony Chacko7e2cf4f2013-01-01 03:20:17 +000042};
43
44static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
45{
46 return (ahw->pci_func & 0xff) | ((ahw->fw_hal_version & 0xff) << 8) |
47 (0xcafe << 16);
48}
49
50/* Allocate mailbox registers */
51int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
52 struct qlcnic_adapter *adapter, u32 type)
53{
54 int i, size;
55 const struct qlcnic_mailbox_metadata *mbx_tbl;
56
57 mbx_tbl = qlcnic_mbx_tbl;
58 size = ARRAY_SIZE(qlcnic_mbx_tbl);
59 for (i = 0; i < size; i++) {
60 if (type == mbx_tbl[i].cmd) {
61 mbx->req.num = mbx_tbl[i].in_args;
62 mbx->rsp.num = mbx_tbl[i].out_args;
63 mbx->req.arg = kcalloc(mbx->req.num,
64 sizeof(u32), GFP_ATOMIC);
65 if (!mbx->req.arg)
66 return -ENOMEM;
67 mbx->rsp.arg = kcalloc(mbx->rsp.num,
68 sizeof(u32), GFP_ATOMIC);
69 if (!mbx->rsp.arg) {
70 kfree(mbx->req.arg);
71 mbx->req.arg = NULL;
72 return -ENOMEM;
73 }
74 memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
75 memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
76 mbx->req.arg[0] = type;
77 break;
78 }
79 }
80 return 0;
81}
82
83/* Free up mailbox registers */
84void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
85{
86 kfree(cmd->req.arg);
87 cmd->req.arg = NULL;
88 kfree(cmd->rsp.arg);
89 cmd->rsp.arg = NULL;
90}
91
Sony Chackobff57d82012-12-04 03:33:56 +000092static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
93{
94 int i;
95
96 for (i = 0; i < adapter->ahw->act_pci_func; i++) {
97 if (adapter->npars[i].pci_func == pci_func)
98 return i;
99 }
100
101 return -1;
102}
103
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000104static u32
105qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
106{
107 u32 rsp;
Himanshu Madhani4bd8e732013-08-02 23:16:01 -0400108 int timeout = 0, err = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000109
110 do {
111 /* give atleast 1ms for firmware to respond */
Narendra K68b3f282012-09-25 07:53:19 +0000112 mdelay(1);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000113
114 if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
115 return QLCNIC_CDRP_RSP_TIMEOUT;
116
Himanshu Madhani4bd8e732013-08-02 23:16:01 -0400117 rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET, &err);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000118 } while (!QLCNIC_CDRP_IS_RSP(rsp));
119
120 return rsp;
121}
122
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000123int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
124 struct qlcnic_cmd_args *cmd)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000125{
Himanshu Madhani4bd8e732013-08-02 23:16:01 -0400126 int i, err = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000127 u32 rsp;
128 u32 signature;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000129 struct pci_dev *pdev = adapter->pdev;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000130 struct qlcnic_hardware_context *ahw = adapter->ahw;
Jitendra Kalsaria114ef382013-02-18 12:06:13 +0000131 const char *fmt;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000132
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000133 signature = qlcnic_get_cmd_signature(ahw);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000134
135 /* Acquire semaphore before accessing CRB */
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000136 if (qlcnic_api_lock(adapter)) {
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000137 cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
138 return cmd->rsp.arg[0];
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000139 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000140
141 QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000142 for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
143 QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000144 QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000145 QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000146 rsp = qlcnic_poll_rsp(adapter);
147
148 if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000149 dev_err(&pdev->dev, "card response timeout.\n");
150 cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000151 } else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
Himanshu Madhani4bd8e732013-08-02 23:16:01 -0400152 cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
Jitendra Kalsaria114ef382013-02-18 12:06:13 +0000153 switch (cmd->rsp.arg[0]) {
154 case QLCNIC_RCODE_INVALID_ARGS:
155 fmt = "CDRP invalid args: [%d]\n";
156 break;
157 case QLCNIC_RCODE_NOT_SUPPORTED:
158 case QLCNIC_RCODE_NOT_IMPL:
159 fmt = "CDRP command not supported: [%d]\n";
160 break;
161 case QLCNIC_RCODE_NOT_PERMITTED:
162 fmt = "CDRP requested action not permitted: [%d]\n";
163 break;
164 case QLCNIC_RCODE_INVALID:
165 fmt = "CDRP invalid or unknown cmd received: [%d]\n";
166 break;
167 case QLCNIC_RCODE_TIMEOUT:
168 fmt = "CDRP command timeout: [%d]\n";
169 break;
170 default:
171 fmt = "CDRP command failed: [%d]\n";
172 break;
173 }
174 dev_err(&pdev->dev, fmt, cmd->rsp.arg[0]);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400175 qlcnic_dump_mbx(adapter, cmd);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000176 } else if (rsp == QLCNIC_CDRP_RSP_OK)
177 cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
178
179 for (i = 1; i < cmd->rsp.num; i++)
Himanshu Madhani4bd8e732013-08-02 23:16:01 -0400180 cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i), &err);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000181
182 /* Release semaphore */
183 qlcnic_api_unlock(adapter);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000184 return cmd->rsp.arg[0];
Anirban Chakraborty18f2f612011-05-12 12:48:33 +0000185}
186
Pratik Pujar8af3f332013-06-22 04:12:05 -0400187int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter, u32 fw_cmd)
Sritej Velagac84e3402013-01-25 10:20:34 +0000188{
189 struct qlcnic_cmd_args cmd;
190 u32 arg1, arg2, arg3;
191 char drv_string[12];
192 int err = 0;
193
194 memset(drv_string, 0, sizeof(drv_string));
195 snprintf(drv_string, sizeof(drv_string), "%d"".""%d"".""%d",
196 _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR,
197 _QLCNIC_LINUX_SUBVERSION);
198
Pratik Pujar8af3f332013-06-22 04:12:05 -0400199 err = qlcnic_alloc_mbx_args(&cmd, adapter, fw_cmd);
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400200 if (err)
201 return err;
202
Sritej Velagac84e3402013-01-25 10:20:34 +0000203 memcpy(&arg1, drv_string, sizeof(u32));
204 memcpy(&arg2, drv_string + 4, sizeof(u32));
205 memcpy(&arg3, drv_string + 8, sizeof(u32));
206
207 cmd.req.arg[1] = arg1;
208 cmd.req.arg[2] = arg2;
209 cmd.req.arg[3] = arg3;
210
211 err = qlcnic_issue_cmd(adapter, &cmd);
212 if (err) {
213 dev_info(&adapter->pdev->dev,
214 "Failed to set driver version in firmware\n");
Himanshu Madhanif91bbcb2013-08-02 23:15:56 -0400215 err = -EIO;
Sritej Velagac84e3402013-01-25 10:20:34 +0000216 }
Himanshu Madhanif91bbcb2013-08-02 23:15:56 -0400217 qlcnic_free_mbx_args(&cmd);
218 return err;
Sritej Velagac84e3402013-01-25 10:20:34 +0000219}
220
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000221int
222qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
223{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000224 int err = 0;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000225 struct qlcnic_cmd_args cmd;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000226 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000227
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000228 if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
229 return err;
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400230 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU);
231 if (err)
232 return err;
233
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000234 cmd.req.arg[1] = recv_ctx->context_id;
235 cmd.req.arg[2] = mtu;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000236
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000237 err = qlcnic_issue_cmd(adapter, &cmd);
238 if (err) {
239 dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
240 err = -EIO;
241 }
242 qlcnic_free_mbx_args(&cmd);
243 return err;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000244}
245
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000246int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000247{
Himanshu Madhani012ec812013-08-21 11:24:10 -0400248 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
249 struct qlcnic_hardware_context *ahw = adapter->ahw;
250 dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
251 struct net_device *netdev = adapter->netdev;
252 u32 temp_intr_crb_mode, temp_rds_crb_mode;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000253 struct qlcnic_cardrsp_rds_ring *prsp_rds;
254 struct qlcnic_cardrsp_sds_ring *prsp_sds;
Himanshu Madhani012ec812013-08-21 11:24:10 -0400255 struct qlcnic_hostrq_rds_ring *prq_rds;
256 struct qlcnic_hostrq_sds_ring *prq_sds;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000257 struct qlcnic_host_rds_ring *rds_ring;
258 struct qlcnic_host_sds_ring *sds_ring;
Himanshu Madhani012ec812013-08-21 11:24:10 -0400259 struct qlcnic_cardrsp_rx_ctx *prsp;
260 struct qlcnic_hostrq_rx_ctx *prq;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000261 u8 i, nrds_rings, nsds_rings;
Himanshu Madhani012ec812013-08-21 11:24:10 -0400262 struct qlcnic_cmd_args cmd;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000263 size_t rq_size, rsp_size;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000264 u32 cap, reg, val, reg2;
Himanshu Madhani012ec812013-08-21 11:24:10 -0400265 u64 phys_addr;
266 u16 temp_u16;
267 void *addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000268 int err;
269
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000270 nrds_rings = adapter->max_rds_rings;
271 nsds_rings = adapter->max_sds_rings;
272
Himanshu Madhani012ec812013-08-21 11:24:10 -0400273 rq_size = SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings,
274 nsds_rings);
275 rsp_size = SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings,
276 nsds_rings);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000277
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000278 addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
Himanshu Madhani012ec812013-08-21 11:24:10 -0400279 &hostrq_phys_addr, GFP_KERNEL);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000280 if (addr == NULL)
281 return -ENOMEM;
Joe Perches43d620c2011-06-16 19:08:06 +0000282 prq = addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000283
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000284 addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
285 &cardrsp_phys_addr, GFP_KERNEL);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000286 if (addr == NULL) {
287 err = -ENOMEM;
288 goto out_free_rq;
289 }
Joe Perches43d620c2011-06-16 19:08:06 +0000290 prsp = addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000291
292 prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
293
schacko8f891382010-06-17 02:56:40 +0000294 cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN
295 | QLCNIC_CAP0_VALIDOFF);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000296 cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
297
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400298 if (qlcnic_check_multi_tx(adapter) &&
299 !adapter->ahw->diag_test) {
Himanshu Madhani012ec812013-08-21 11:24:10 -0400300 cap |= QLCNIC_CAP0_TX_MULTI;
301 } else {
302 temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
303 prq->valid_field_offset = cpu_to_le16(temp_u16);
304 prq->txrx_sds_binding = nsds_rings - 1;
305 temp_intr_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED;
306 prq->host_int_crb_mode = cpu_to_le32(temp_intr_crb_mode);
307 temp_rds_crb_mode = QLCNIC_HOST_RDS_CRB_MODE_UNIQUE;
308 prq->host_rds_crb_mode = cpu_to_le32(temp_rds_crb_mode);
309 }
schacko8f891382010-06-17 02:56:40 +0000310
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000311 prq->capabilities[0] = cpu_to_le32(cap);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000312
313 prq->num_rds_rings = cpu_to_le16(nrds_rings);
314 prq->num_sds_rings = cpu_to_le16(nsds_rings);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000315 prq->rds_ring_offset = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000316
317 val = le32_to_cpu(prq->rds_ring_offset) +
318 (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings);
319 prq->sds_ring_offset = cpu_to_le32(val);
320
321 prq_rds = (struct qlcnic_hostrq_rds_ring *)(prq->data +
322 le32_to_cpu(prq->rds_ring_offset));
323
324 for (i = 0; i < nrds_rings; i++) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000325 rds_ring = &recv_ctx->rds_rings[i];
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000326 rds_ring->producer = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000327 prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
328 prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
329 prq_rds[i].ring_kind = cpu_to_le32(i);
330 prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
331 }
332
333 prq_sds = (struct qlcnic_hostrq_sds_ring *)(prq->data +
334 le32_to_cpu(prq->sds_ring_offset));
335
336 for (i = 0; i < nsds_rings; i++) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000337 sds_ring = &recv_ctx->sds_rings[i];
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000338 sds_ring->consumer = 0;
339 memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000340 prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
341 prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400342 if (qlcnic_check_multi_tx(adapter) &&
343 !adapter->ahw->diag_test)
Himanshu Madhani012ec812013-08-21 11:24:10 -0400344 prq_sds[i].msi_index = cpu_to_le16(ahw->intr_tbl[i].id);
345 else
346 prq_sds[i].msi_index = cpu_to_le16(i);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000347 }
348
349 phys_addr = hostrq_phys_addr;
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400350 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX);
351 if (err)
352 goto out_free_rsp;
353
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000354 cmd.req.arg[1] = MSD(phys_addr);
355 cmd.req.arg[2] = LSD(phys_addr);
356 cmd.req.arg[3] = rq_size;
357 err = qlcnic_issue_cmd(adapter, &cmd);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000358 if (err) {
359 dev_err(&adapter->pdev->dev,
360 "Failed to create rx ctx in firmware%d\n", err);
361 goto out_free_rsp;
362 }
363
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000364 prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
365 &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
366
367 for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
368 rds_ring = &recv_ctx->rds_rings[i];
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000369 reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400370 rds_ring->crb_rcv_producer = ahw->pci_base0 + reg;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000371 }
372
373 prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
374 &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
375
376 for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) {
377 sds_ring = &recv_ctx->sds_rings[i];
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000378 reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400379 if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test)
Himanshu Madhani012ec812013-08-21 11:24:10 -0400380 reg2 = ahw->intr_tbl[i].src;
381 else
382 reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000383
Himanshu Madhani012ec812013-08-21 11:24:10 -0400384 sds_ring->crb_intr_mask = ahw->pci_base0 + reg2;
385 sds_ring->crb_sts_consumer = ahw->pci_base0 + reg;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000386 }
387
388 recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
389 recv_ctx->context_id = le16_to_cpu(prsp->context_id);
390 recv_ctx->virt_port = prsp->virt_port;
391
Himanshu Madhani012ec812013-08-21 11:24:10 -0400392 netdev_info(netdev, "Rx Context[%d] Created, state 0x%x\n",
393 recv_ctx->context_id, recv_ctx->state);
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400394 qlcnic_free_mbx_args(&cmd);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400395
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000396out_free_rsp:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000397 dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400398 cardrsp_phys_addr);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000399out_free_rq:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000400 dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400401
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000402 return err;
403}
404
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000405void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000406{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000407 int err;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000408 struct qlcnic_cmd_args cmd;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000409 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000410
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400411 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX);
412 if (err)
413 return;
414
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000415 cmd.req.arg[1] = recv_ctx->context_id;
416 err = qlcnic_issue_cmd(adapter, &cmd);
417 if (err)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000418 dev_err(&adapter->pdev->dev,
419 "Failed to destroy rx ctx in firmware\n");
Amit Kumar Salechad626ad42010-06-22 03:19:04 +0000420
421 recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000422 qlcnic_free_mbx_args(&cmd);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000423}
424
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000425int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
426 struct qlcnic_host_tx_ring *tx_ring,
427 int ring)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000428{
Himanshu Madhani012ec812013-08-21 11:24:10 -0400429 struct qlcnic_hardware_context *ahw = adapter->ahw;
430 struct net_device *netdev = adapter->netdev;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000431 struct qlcnic_hostrq_tx_ctx *prq;
432 struct qlcnic_hostrq_cds_ring *prq_cds;
433 struct qlcnic_cardrsp_tx_ctx *prsp;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000434 struct qlcnic_cmd_args cmd;
Himanshu Madhani012ec812013-08-21 11:24:10 -0400435 u32 temp, intr_mask, temp_int_crb_mode;
436 dma_addr_t rq_phys_addr, rsp_phys_addr;
437 int temp_nsds_rings, index, err;
438 void *rq_addr, *rsp_addr;
439 size_t rq_size, rsp_size;
440 u64 phys_addr;
441 u16 msix_id;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000442
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000443 /* reset host resources */
444 tx_ring->producer = 0;
445 tx_ring->sw_consumer = 0;
446 *(tx_ring->hw_consumer) = 0;
447
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000448 rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000449 rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
Joe Perches1f9061d22013-03-15 07:23:58 +0000450 &rq_phys_addr, GFP_KERNEL | __GFP_ZERO);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000451 if (!rq_addr)
452 return -ENOMEM;
453
454 rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000455 rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
Joe Perches1f9061d22013-03-15 07:23:58 +0000456 &rsp_phys_addr, GFP_KERNEL | __GFP_ZERO);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000457 if (!rsp_addr) {
458 err = -ENOMEM;
459 goto out_free_rq;
460 }
461
Joe Perches43d620c2011-06-16 19:08:06 +0000462 prq = rq_addr;
Joe Perches43d620c2011-06-16 19:08:06 +0000463 prsp = rsp_addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000464
465 prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
466
467 temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN |
Himanshu Madhani012ec812013-08-21 11:24:10 -0400468 QLCNIC_CAP0_LSO);
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400469 if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test)
Himanshu Madhani012ec812013-08-21 11:24:10 -0400470 temp |= QLCNIC_CAP0_TX_MULTI;
471
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000472 prq->capabilities[0] = cpu_to_le32(temp);
473
Himanshu Madhani012ec812013-08-21 11:24:10 -0400474 if (qlcnic_check_multi_tx(adapter) &&
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400475 !adapter->ahw->diag_test) {
Himanshu Madhani012ec812013-08-21 11:24:10 -0400476 temp_nsds_rings = adapter->max_sds_rings;
477 index = temp_nsds_rings + ring;
478 msix_id = ahw->intr_tbl[index].id;
479 prq->msi_index = cpu_to_le16(msix_id);
480 } else {
481 temp_int_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED;
482 prq->host_int_crb_mode = cpu_to_le32(temp_int_crb_mode);
483 prq->msi_index = 0;
484 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000485
486 prq->interrupt_ctl = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000487 prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
488
489 prq_cds = &prq->cds_ring;
490
491 prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
492 prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
493
494 phys_addr = rq_phys_addr;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000495
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400496 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
497 if (err)
498 goto out_free_rsp;
499
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000500 cmd.req.arg[1] = MSD(phys_addr);
501 cmd.req.arg[2] = LSD(phys_addr);
502 cmd.req.arg[3] = rq_size;
503 err = qlcnic_issue_cmd(adapter, &cmd);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000504
505 if (err == QLCNIC_RCODE_SUCCESS) {
Himanshu Madhani012ec812013-08-21 11:24:10 -0400506 tx_ring->state = le32_to_cpu(prsp->host_ctx_state);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000507 temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000508 tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000509 tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400510 if (qlcnic_check_multi_tx(adapter) &&
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400511 !adapter->ahw->diag_test &&
Himanshu Madhani012ec812013-08-21 11:24:10 -0400512 (adapter->flags & QLCNIC_MSIX_ENABLED)) {
513 index = adapter->max_sds_rings + ring;
514 intr_mask = ahw->intr_tbl[index].src;
515 tx_ring->crb_intr_mask = ahw->pci_base0 + intr_mask;
516 }
517
518 netdev_info(netdev, "Tx Context[0x%x] Created, state 0x%x\n",
519 tx_ring->ctx_id, tx_ring->state);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000520 } else {
Himanshu Madhani012ec812013-08-21 11:24:10 -0400521 netdev_err(netdev, "Failed to create tx ctx in firmware%d\n",
522 err);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000523 err = -EIO;
524 }
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400525 qlcnic_free_mbx_args(&cmd);
526
527out_free_rsp:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000528 dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000529 rsp_phys_addr);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000530out_free_rq:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000531 dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000532
533 return err;
534}
535
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000536void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
537 struct qlcnic_host_tx_ring *tx_ring)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000538{
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000539 struct qlcnic_cmd_args cmd;
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400540 int ret;
Sritej Velaga9254b752011-08-29 12:50:29 +0000541
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400542 ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
543 if (ret)
544 return;
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000545
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000546 cmd.req.arg[1] = tx_ring->ctx_id;
547 if (qlcnic_issue_cmd(adapter, &cmd))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000548 dev_err(&adapter->pdev->dev,
549 "Failed to destroy tx ctx in firmware\n");
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000550 qlcnic_free_mbx_args(&cmd);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000551}
552
553int
Sony Chacko7e610ca2011-04-28 11:48:19 +0000554qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000555{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000556 int err;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000557 struct qlcnic_cmd_args cmd;
Sritej Velaga9254b752011-08-29 12:50:29 +0000558
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400559 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT);
560 if (err)
561 return err;
562
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000563 cmd.req.arg[1] = config;
564 err = qlcnic_issue_cmd(adapter, &cmd);
565 qlcnic_free_mbx_args(&cmd);
566 return err;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000567}
568
569int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
570{
571 void *addr;
Sony Chacko4be41e92013-01-01 03:20:20 +0000572 int err, ring;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000573 struct qlcnic_recv_context *recv_ctx;
574 struct qlcnic_host_rds_ring *rds_ring;
575 struct qlcnic_host_sds_ring *sds_ring;
576 struct qlcnic_host_tx_ring *tx_ring;
Sony Chacko4be41e92013-01-01 03:20:20 +0000577 __le32 *ptr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000578
579 struct pci_dev *pdev = adapter->pdev;
580
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000581 recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000582
Sony Chacko4be41e92013-01-01 03:20:20 +0000583 for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
584 tx_ring = &adapter->tx_ring[ring];
585 ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
586 &tx_ring->hw_cons_phys_addr,
587 GFP_KERNEL);
Joe Perchesd0320f72013-03-14 13:07:21 +0000588 if (ptr == NULL)
Sony Chacko4be41e92013-01-01 03:20:20 +0000589 return -ENOMEM;
Joe Perchesd0320f72013-03-14 13:07:21 +0000590
Sony Chacko4be41e92013-01-01 03:20:20 +0000591 tx_ring->hw_consumer = ptr;
592 /* cmd desc ring */
593 addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
594 &tx_ring->phys_addr,
595 GFP_KERNEL);
Sony Chacko4be41e92013-01-01 03:20:20 +0000596 if (addr == NULL) {
Sony Chacko4be41e92013-01-01 03:20:20 +0000597 err = -ENOMEM;
598 goto err_out_free;
599 }
600
601 tx_ring->desc_head = addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000602 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000603
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000604 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
605 rds_ring = &recv_ctx->rds_rings[ring];
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000606 addr = dma_alloc_coherent(&adapter->pdev->dev,
Joe Perchesd0320f72013-03-14 13:07:21 +0000607 RCV_DESC_RINGSIZE(rds_ring),
608 &rds_ring->phys_addr, GFP_KERNEL);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000609 if (addr == NULL) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000610 err = -ENOMEM;
611 goto err_out_free;
612 }
Joe Perches43d620c2011-06-16 19:08:06 +0000613 rds_ring->desc_head = addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000614
615 }
616
617 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
618 sds_ring = &recv_ctx->sds_rings[ring];
619
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000620 addr = dma_alloc_coherent(&adapter->pdev->dev,
Joe Perchesd0320f72013-03-14 13:07:21 +0000621 STATUS_DESC_RINGSIZE(sds_ring),
622 &sds_ring->phys_addr, GFP_KERNEL);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000623 if (addr == NULL) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000624 err = -ENOMEM;
625 goto err_out_free;
626 }
Joe Perches43d620c2011-06-16 19:08:06 +0000627 sds_ring->desc_head = addr;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000628 }
629
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000630 return 0;
631
632err_out_free:
633 qlcnic_free_hw_resources(adapter);
634 return err;
635}
636
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000637int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000638{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000639 int i, err, ring;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000640
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000641 if (dev->flags & QLCNIC_NEED_FLR) {
642 pci_reset_function(dev->pdev);
643 dev->flags &= ~QLCNIC_NEED_FLR;
Rajesh Borundiab0044bc2010-11-23 01:25:21 +0000644 }
Rajesh Borundiac21fd482010-11-16 14:08:06 +0000645
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000646 if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) {
647 if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) {
648 err = qlcnic_83xx_config_intrpt(dev, 1);
649 if (err)
650 return err;
651 }
652 }
653
Himanshu Madhani012ec812013-08-21 11:24:10 -0400654 if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) &&
655 qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test) {
656 err = qlcnic_82xx_mq_intrpt(dev, 1);
657 if (err)
658 return err;
659 }
660
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000661 err = qlcnic_fw_cmd_create_rx_ctx(dev);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000662 if (err)
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000663 goto err_out;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000664
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000665 for (ring = 0; ring < dev->max_drv_tx_rings; ring++) {
666 err = qlcnic_fw_cmd_create_tx_ctx(dev,
667 &dev->tx_ring[ring],
668 ring);
669 if (err) {
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000670 qlcnic_fw_cmd_del_rx_ctx(dev);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000671 if (ring == 0)
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000672 goto err_out;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000673
674 for (i = 0; i < ring; i++)
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000675 qlcnic_fw_cmd_del_tx_ctx(dev, &dev->tx_ring[i]);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000676
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000677 goto err_out;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000678 }
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000679 }
680
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000681 set_bit(__QLCNIC_FW_ATTACHED, &dev->state);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400682
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000683 return 0;
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000684
685err_out:
Himanshu Madhani012ec812013-08-21 11:24:10 -0400686 if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) &&
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400687 qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test)
688 qlcnic_82xx_config_intrpt(dev, 0);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400689
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000690 if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) {
691 if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
692 qlcnic_83xx_config_intrpt(dev, 0);
693 }
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400694
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000695 return err;
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000696}
697
698void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
699{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000700 int ring;
701
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000702 if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000703 qlcnic_fw_cmd_del_rx_ctx(adapter);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000704 for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
Rajesh Borundia7cb03b22013-03-29 05:46:37 +0000705 qlcnic_fw_cmd_del_tx_ctx(adapter,
706 &adapter->tx_ring[ring]);
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000707
Himanshu Madhani012ec812013-08-21 11:24:10 -0400708 if (qlcnic_82xx_check(adapter) &&
709 (adapter->flags & QLCNIC_MSIX_ENABLED) &&
Himanshu Madhanic2c5e3a2013-08-21 11:24:12 -0400710 qlcnic_check_multi_tx(adapter) &&
711 !adapter->ahw->diag_test)
712 qlcnic_82xx_config_intrpt(adapter, 0);
Himanshu Madhani012ec812013-08-21 11:24:10 -0400713
Sucheta Chakraborty7dd90cf2013-02-18 12:06:14 +0000714 if (qlcnic_83xx_check(adapter) &&
715 (adapter->flags & QLCNIC_MSIX_ENABLED)) {
716 if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
717 qlcnic_83xx_config_intrpt(adapter, 0);
718 }
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000719 /* Allow dma queues to drain after context reset */
Shahed Shaikhf57da7a2013-06-21 12:09:42 -0400720 mdelay(20);
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000721 }
722}
723
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000724void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
725{
726 struct qlcnic_recv_context *recv_ctx;
727 struct qlcnic_host_rds_ring *rds_ring;
728 struct qlcnic_host_sds_ring *sds_ring;
729 struct qlcnic_host_tx_ring *tx_ring;
730 int ring;
731
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000732 recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000733
Sony Chacko4be41e92013-01-01 03:20:20 +0000734 for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
735 tx_ring = &adapter->tx_ring[ring];
736 if (tx_ring->hw_consumer != NULL) {
737 dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
738 tx_ring->hw_consumer,
739 tx_ring->hw_cons_phys_addr);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000740
Sony Chacko4be41e92013-01-01 03:20:20 +0000741 tx_ring->hw_consumer = NULL;
742 }
743
744 if (tx_ring->desc_head != NULL) {
745 dma_free_coherent(&adapter->pdev->dev,
746 TX_DESC_RINGSIZE(tx_ring),
747 tx_ring->desc_head,
748 tx_ring->phys_addr);
749 tx_ring->desc_head = NULL;
750 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000751 }
752
753 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
754 rds_ring = &recv_ctx->rds_rings[ring];
755
756 if (rds_ring->desc_head != NULL) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000757 dma_free_coherent(&adapter->pdev->dev,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000758 RCV_DESC_RINGSIZE(rds_ring),
759 rds_ring->desc_head,
760 rds_ring->phys_addr);
761 rds_ring->desc_head = NULL;
762 }
763 }
764
765 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
766 sds_ring = &recv_ctx->sds_rings[ring];
767
768 if (sds_ring->desc_head != NULL) {
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000769 dma_free_coherent(&adapter->pdev->dev,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000770 STATUS_DESC_RINGSIZE(sds_ring),
771 sds_ring->desc_head,
772 sds_ring->phys_addr);
773 sds_ring->desc_head = NULL;
774 }
775 }
776}
777
Himanshu Madhani012ec812013-08-21 11:24:10 -0400778int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type)
779{
780 struct qlcnic_hardware_context *ahw = adapter->ahw;
781 struct net_device *netdev = adapter->netdev;
782 struct qlcnic_cmd_args cmd;
783 u32 type, val;
784 int i, err = 0;
785
786 for (i = 0; i < ahw->num_msix; i++) {
787 qlcnic_alloc_mbx_args(&cmd, adapter,
788 QLCNIC_CMD_MQ_TX_CONFIG_INTR);
789 type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
790 val = type | (ahw->intr_tbl[i].type << 4);
791 if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
792 val |= (ahw->intr_tbl[i].id << 16);
793 cmd.req.arg[1] = val;
794 err = qlcnic_issue_cmd(adapter, &cmd);
795 if (err) {
796 netdev_err(netdev, "Failed to %s interrupts %d\n",
797 op_type == QLCNIC_INTRPT_ADD ? "Add" :
798 "Delete", err);
799 qlcnic_free_mbx_args(&cmd);
800 return err;
801 }
802 val = cmd.rsp.arg[1];
803 if (LSB(val)) {
804 netdev_info(netdev,
805 "failed to configure interrupt for %d\n",
806 ahw->intr_tbl[i].id);
807 continue;
808 }
809 if (op_type) {
810 ahw->intr_tbl[i].id = MSW(val);
811 ahw->intr_tbl[i].enabled = 1;
812 ahw->intr_tbl[i].src = cmd.rsp.arg[2];
813 } else {
814 ahw->intr_tbl[i].id = i;
815 ahw->intr_tbl[i].enabled = 0;
816 ahw->intr_tbl[i].src = 0;
817 }
818 qlcnic_free_mbx_args(&cmd);
819 }
820
821 return err;
822}
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000823
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000824int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000825{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000826 int err, i;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000827 struct qlcnic_cmd_args cmd;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000828 u32 mac_low, mac_high;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000829
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400830 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
831 if (err)
832 return err;
833
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000834 cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
835 err = qlcnic_issue_cmd(adapter, &cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000836
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000837 if (err == QLCNIC_RCODE_SUCCESS) {
838 mac_low = cmd.rsp.arg[1];
839 mac_high = cmd.rsp.arg[2];
840
841 for (i = 0; i < 2; i++)
842 mac[i] = (u8) (mac_high >> ((1 - i) * 8));
843 for (i = 2; i < 6; i++)
844 mac[i] = (u8) (mac_low >> ((5 - i) * 8));
845 } else {
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000846 dev_err(&adapter->pdev->dev,
847 "Failed to get mac address%d\n", err);
848 err = -EIO;
849 }
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000850 qlcnic_free_mbx_args(&cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000851 return err;
852}
853
854/* Get info of a NIC partition */
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000855int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
856 struct qlcnic_info *npar_info, u8 func_id)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000857{
858 int err;
859 dma_addr_t nic_dma_t;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000860 const struct qlcnic_info_le *nic_info;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000861 void *nic_info_addr;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000862 struct qlcnic_cmd_args cmd;
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000863 size_t nic_size = sizeof(struct qlcnic_info_le);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000864
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000865 nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
Joe Perches1f9061d22013-03-15 07:23:58 +0000866 &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000867 if (!nic_info_addr)
868 return -ENOMEM;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000869
Joe Perches43d620c2011-06-16 19:08:06 +0000870 nic_info = nic_info_addr;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000871
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400872 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
873 if (err)
874 goto out_free_dma;
875
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000876 cmd.req.arg[1] = MSD(nic_dma_t);
877 cmd.req.arg[2] = LSD(nic_dma_t);
878 cmd.req.arg[3] = (func_id << 16 | nic_size);
879 err = qlcnic_issue_cmd(adapter, &cmd);
880 if (err != QLCNIC_RCODE_SUCCESS) {
881 dev_err(&adapter->pdev->dev,
882 "Failed to get nic info%d\n", err);
883 err = -EIO;
884 } else {
Anirban Chakrabortycea89752010-07-13 20:33:35 +0000885 npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
886 npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000887 npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
888 npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000889 npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
890 npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
891 npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
892 npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000893 npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
894 npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000895 }
896
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400897 qlcnic_free_mbx_args(&cmd);
898out_free_dma:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000899 dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000900 nic_dma_t);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000901
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000902 return err;
903}
904
905/* Configure a NIC partition */
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000906int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
907 struct qlcnic_info *nic)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000908{
909 int err = -EIO;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000910 dma_addr_t nic_dma_t;
911 void *nic_info_addr;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000912 struct qlcnic_cmd_args cmd;
Shahed Shaikh63507592012-11-23 23:56:52 +0000913 struct qlcnic_info_le *nic_info;
914 size_t nic_size = sizeof(struct qlcnic_info_le);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000915
Sony Chacko79788452012-12-04 03:33:53 +0000916 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000917 return err;
918
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000919 nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
Joe Perches1f9061d22013-03-15 07:23:58 +0000920 &nic_dma_t, GFP_KERNEL | __GFP_ZERO);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000921 if (!nic_info_addr)
922 return -ENOMEM;
923
Joe Perches43d620c2011-06-16 19:08:06 +0000924 nic_info = nic_info_addr;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000925
926 nic_info->pci_func = cpu_to_le16(nic->pci_func);
927 nic_info->op_mode = cpu_to_le16(nic->op_mode);
928 nic_info->phys_port = cpu_to_le16(nic->phys_port);
929 nic_info->switch_mode = cpu_to_le16(nic->switch_mode);
930 nic_info->capabilities = cpu_to_le32(nic->capabilities);
931 nic_info->max_mac_filters = nic->max_mac_filters;
932 nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques);
933 nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques);
934 nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
935 nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
936
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400937 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
938 if (err)
939 goto out_free_dma;
940
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000941 cmd.req.arg[1] = MSD(nic_dma_t);
942 cmd.req.arg[2] = LSD(nic_dma_t);
943 cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
944 err = qlcnic_issue_cmd(adapter, &cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000945
946 if (err != QLCNIC_RCODE_SUCCESS) {
947 dev_err(&adapter->pdev->dev,
948 "Failed to set nic info%d\n", err);
949 err = -EIO;
950 }
951
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000952 qlcnic_free_mbx_args(&cmd);
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400953out_free_dma:
954 dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
955 nic_dma_t);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000956
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000957 return err;
958}
959
960/* Get PCI Info of a partition */
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000961int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
962 struct qlcnic_pci_info *pci_info)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000963{
964 int err = 0, i;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000965 struct qlcnic_cmd_args cmd;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000966 dma_addr_t pci_info_dma_t;
Shahed Shaikh63507592012-11-23 23:56:52 +0000967 struct qlcnic_pci_info_le *npar;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000968 void *pci_info_addr;
Shahed Shaikh63507592012-11-23 23:56:52 +0000969 size_t npar_size = sizeof(struct qlcnic_pci_info_le);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000970 size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
971
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000972 pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
Joe Perches1f9061d22013-03-15 07:23:58 +0000973 &pci_info_dma_t,
974 GFP_KERNEL | __GFP_ZERO);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000975 if (!pci_info_addr)
976 return -ENOMEM;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000977
Joe Perches43d620c2011-06-16 19:08:06 +0000978 npar = pci_info_addr;
Shahed Shaikhb6b43162013-06-22 04:12:00 -0400979 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
980 if (err)
981 goto out_free_dma;
982
Sony Chacko7e2cf4f2013-01-01 03:20:17 +0000983 cmd.req.arg[1] = MSD(pci_info_dma_t);
984 cmd.req.arg[2] = LSD(pci_info_dma_t);
985 cmd.req.arg[3] = pci_size;
986 err = qlcnic_issue_cmd(adapter, &cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000987
Sony Chackobff57d82012-12-04 03:33:56 +0000988 adapter->ahw->act_pci_func = 0;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000989 if (err == QLCNIC_RCODE_SUCCESS) {
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000990 for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
Sucheta Chakrabortya1c0c452010-10-04 04:20:14 +0000991 pci_info->id = le16_to_cpu(npar->id);
992 pci_info->active = le16_to_cpu(npar->active);
993 pci_info->type = le16_to_cpu(npar->type);
Sony Chackobff57d82012-12-04 03:33:56 +0000994 if (pci_info->type == QLCNIC_TYPE_NIC)
995 adapter->ahw->act_pci_func++;
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000996 pci_info->default_port =
Sucheta Chakrabortya1c0c452010-10-04 04:20:14 +0000997 le16_to_cpu(npar->default_port);
Rajesh K Borundia346fe762010-06-29 08:01:20 +0000998 pci_info->tx_min_bw =
Sucheta Chakrabortya1c0c452010-10-04 04:20:14 +0000999 le16_to_cpu(npar->tx_min_bw);
Rajesh K Borundia346fe762010-06-29 08:01:20 +00001000 pci_info->tx_max_bw =
Sucheta Chakrabortya1c0c452010-10-04 04:20:14 +00001001 le16_to_cpu(npar->tx_max_bw);
Rajesh K Borundia346fe762010-06-29 08:01:20 +00001002 memcpy(pci_info->mac, npar->mac, ETH_ALEN);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001003 }
1004 } else {
1005 dev_err(&adapter->pdev->dev,
1006 "Failed to get PCI Info%d\n", err);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001007 err = -EIO;
1008 }
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001009
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001010 qlcnic_free_mbx_args(&cmd);
1011out_free_dma:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001012 dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001013 pci_info_dma_t);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001014
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001015 return err;
1016}
1017
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001018/* Configure eSwitch for port mirroring */
1019int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
Manish Chopraee9e8b62013-05-23 21:04:35 +00001020 u8 enable_mirroring, u8 pci_func)
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001021{
Manish Chopraee9e8b62013-05-23 21:04:35 +00001022 struct device *dev = &adapter->pdev->dev;
1023 struct qlcnic_cmd_args cmd;
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001024 int err = -EIO;
1025 u32 arg1;
1026
Sony Chacko79788452012-12-04 03:33:53 +00001027 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
1028 !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001029 return err;
1030
1031 arg1 = id | (enable_mirroring ? BIT_4 : 0);
1032 arg1 |= pci_func << 8;
1033
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001034 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1035 QLCNIC_CMD_SET_PORTMIRRORING);
1036 if (err)
1037 return err;
1038
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001039 cmd.req.arg[1] = arg1;
1040 err = qlcnic_issue_cmd(adapter, &cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001041
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001042 if (err != QLCNIC_RCODE_SUCCESS)
Manish Chopraee9e8b62013-05-23 21:04:35 +00001043 dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n",
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001044 pci_func, id);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001045 else
Manish Chopraee9e8b62013-05-23 21:04:35 +00001046 dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n",
1047 pci_func, id);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001048 qlcnic_free_mbx_args(&cmd);
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +00001049
1050 return err;
1051}
1052
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001053int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
1054 const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
1055
Shahed Shaikh63507592012-11-23 23:56:52 +00001056 size_t stats_size = sizeof(struct qlcnic_esw_stats_le);
1057 struct qlcnic_esw_stats_le *stats;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001058 dma_addr_t stats_dma_t;
1059 void *stats_addr;
1060 u32 arg1;
Anirban Chakraborty7777de92011-09-13 08:06:18 +00001061 struct qlcnic_cmd_args cmd;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001062 int err;
1063
1064 if (esw_stats == NULL)
1065 return -ENOMEM;
1066
Sony Chacko79788452012-12-04 03:33:53 +00001067 if ((adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) &&
1068 (func != adapter->ahw->pci_func)) {
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001069 dev_err(&adapter->pdev->dev,
1070 "Not privilege to query stats for func=%d", func);
1071 return -EIO;
1072 }
1073
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001074 stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
Joe Perches1f9061d22013-03-15 07:23:58 +00001075 &stats_dma_t, GFP_KERNEL | __GFP_ZERO);
Joe Perchesd0320f72013-03-14 13:07:21 +00001076 if (!stats_addr)
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001077 return -ENOMEM;
Joe Perchesd0320f72013-03-14 13:07:21 +00001078
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001079 arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
1080 arg1 |= rx_tx << 15 | stats_size << 16;
1081
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001082 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1083 QLCNIC_CMD_GET_ESWITCH_STATS);
1084 if (err)
1085 goto out_free_dma;
1086
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001087 cmd.req.arg[1] = arg1;
1088 cmd.req.arg[2] = MSD(stats_dma_t);
1089 cmd.req.arg[3] = LSD(stats_dma_t);
1090 err = qlcnic_issue_cmd(adapter, &cmd);
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001091
Amit Kumar Salecha63e74e92010-08-19 05:08:30 +00001092 if (!err) {
Joe Perches43d620c2011-06-16 19:08:06 +00001093 stats = stats_addr;
Amit Kumar Salecha63e74e92010-08-19 05:08:30 +00001094 esw_stats->context_id = le16_to_cpu(stats->context_id);
1095 esw_stats->version = le16_to_cpu(stats->version);
1096 esw_stats->size = le16_to_cpu(stats->size);
1097 esw_stats->multicast_frames =
1098 le64_to_cpu(stats->multicast_frames);
1099 esw_stats->broadcast_frames =
1100 le64_to_cpu(stats->broadcast_frames);
1101 esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames);
1102 esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames);
1103 esw_stats->local_frames = le64_to_cpu(stats->local_frames);
1104 esw_stats->errors = le64_to_cpu(stats->errors);
1105 esw_stats->numbytes = le64_to_cpu(stats->numbytes);
1106 }
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001107
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001108 qlcnic_free_mbx_args(&cmd);
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001109out_free_dma:
1110 dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
1111 stats_dma_t);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001112
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001113 return err;
1114}
1115
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001116/* This routine will retrieve the MAC statistics from firmware */
1117int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
1118 struct qlcnic_mac_statistics *mac_stats)
1119{
Shahed Shaikh63507592012-11-23 23:56:52 +00001120 struct qlcnic_mac_statistics_le *stats;
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001121 struct qlcnic_cmd_args cmd;
Shahed Shaikh63507592012-11-23 23:56:52 +00001122 size_t stats_size = sizeof(struct qlcnic_mac_statistics_le);
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001123 dma_addr_t stats_dma_t;
1124 void *stats_addr;
1125 int err;
1126
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001127 if (mac_stats == NULL)
1128 return -ENOMEM;
1129
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001130 stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
Joe Perches1f9061d22013-03-15 07:23:58 +00001131 &stats_dma_t, GFP_KERNEL | __GFP_ZERO);
Joe Perchesd0320f72013-03-14 13:07:21 +00001132 if (!stats_addr)
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001133 return -ENOMEM;
Joe Perchesd0320f72013-03-14 13:07:21 +00001134
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001135 err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
1136 if (err)
1137 goto out_free_dma;
1138
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001139 cmd.req.arg[1] = stats_size << 16;
1140 cmd.req.arg[2] = MSD(stats_dma_t);
1141 cmd.req.arg[3] = LSD(stats_dma_t);
1142 err = qlcnic_issue_cmd(adapter, &cmd);
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001143 if (!err) {
1144 stats = stats_addr;
1145 mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
1146 mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
1147 mac_stats->mac_tx_mcast_pkts =
1148 le64_to_cpu(stats->mac_tx_mcast_pkts);
1149 mac_stats->mac_tx_bcast_pkts =
1150 le64_to_cpu(stats->mac_tx_bcast_pkts);
1151 mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
1152 mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
1153 mac_stats->mac_rx_mcast_pkts =
1154 le64_to_cpu(stats->mac_rx_mcast_pkts);
1155 mac_stats->mac_rx_length_error =
1156 le64_to_cpu(stats->mac_rx_length_error);
1157 mac_stats->mac_rx_length_small =
1158 le64_to_cpu(stats->mac_rx_length_small);
1159 mac_stats->mac_rx_length_large =
1160 le64_to_cpu(stats->mac_rx_length_large);
1161 mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
1162 mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
1163 mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001164 } else {
1165 dev_err(&adapter->pdev->dev,
1166 "%s: Get mac stats failed, err=%d.\n", __func__, err);
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001167 }
1168
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001169 qlcnic_free_mbx_args(&cmd);
1170
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001171out_free_dma:
1172 dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
1173 stats_dma_t);
1174
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001175 return err;
1176}
1177
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001178int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
1179 const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
1180
1181 struct __qlcnic_esw_statistics port_stats;
1182 u8 i;
1183 int ret = -EIO;
1184
1185 if (esw_stats == NULL)
1186 return -ENOMEM;
Sony Chacko79788452012-12-04 03:33:53 +00001187 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001188 return -EIO;
1189 if (adapter->npars == NULL)
1190 return -EIO;
1191
Amit Kumar Salechaef182802010-10-04 04:20:10 +00001192 memset(esw_stats, 0, sizeof(u64));
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001193 esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
1194 esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
1195 esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
1196 esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
1197 esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
1198 esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
1199 esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001200 esw_stats->context_id = eswitch;
1201
Sony Chackobff57d82012-12-04 03:33:56 +00001202 for (i = 0; i < adapter->ahw->act_pci_func; i++) {
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001203 if (adapter->npars[i].phy_port != eswitch)
1204 continue;
1205
1206 memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
Sony Chackobff57d82012-12-04 03:33:56 +00001207 if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func,
1208 rx_tx, &port_stats))
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001209 continue;
1210
1211 esw_stats->size = port_stats.size;
1212 esw_stats->version = port_stats.version;
Amit Kumar Salechaef182802010-10-04 04:20:10 +00001213 QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames,
1214 port_stats.unicast_frames);
1215 QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames,
1216 port_stats.multicast_frames);
1217 QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames,
1218 port_stats.broadcast_frames);
1219 QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames,
1220 port_stats.dropped_frames);
1221 QLCNIC_ADD_ESW_STATS(esw_stats->errors,
1222 port_stats.errors);
1223 QLCNIC_ADD_ESW_STATS(esw_stats->local_frames,
1224 port_stats.local_frames);
1225 QLCNIC_ADD_ESW_STATS(esw_stats->numbytes,
1226 port_stats.numbytes);
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001227 ret = 0;
1228 }
1229 return ret;
1230}
1231
1232int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
1233 const u8 port, const u8 rx_tx)
1234{
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001235 int err;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001236 u32 arg1;
Anirban Chakraborty7777de92011-09-13 08:06:18 +00001237 struct qlcnic_cmd_args cmd;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001238
Sony Chacko79788452012-12-04 03:33:53 +00001239 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001240 return -EIO;
1241
1242 if (func_esw == QLCNIC_STATS_PORT) {
1243 if (port >= QLCNIC_MAX_PCI_FUNC)
1244 goto err_ret;
1245 } else if (func_esw == QLCNIC_STATS_ESWITCH) {
1246 if (port >= QLCNIC_NIU_MAX_XG_PORTS)
1247 goto err_ret;
1248 } else {
1249 goto err_ret;
1250 }
1251
1252 if (rx_tx > QLCNIC_QUERY_TX_COUNTER)
1253 goto err_ret;
1254
1255 arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
1256 arg1 |= BIT_14 | rx_tx << 15;
1257
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001258 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1259 QLCNIC_CMD_GET_ESWITCH_STATS);
1260 if (err)
1261 return err;
1262
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001263 cmd.req.arg[1] = arg1;
1264 err = qlcnic_issue_cmd(adapter, &cmd);
1265 qlcnic_free_mbx_args(&cmd);
1266 return err;
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001267
1268err_ret:
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001269 dev_err(&adapter->pdev->dev,
1270 "Invalid args func_esw %d port %d rx_ctx %d\n",
1271 func_esw, port, rx_tx);
Amit Kumar Salechab6021212010-08-17 00:34:22 +00001272 return -EIO;
1273}
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001274
Manish Chopraee9e8b62013-05-23 21:04:35 +00001275static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
1276 u32 *arg1, u32 *arg2)
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001277{
Manish Chopraee9e8b62013-05-23 21:04:35 +00001278 struct device *dev = &adapter->pdev->dev;
Anirban Chakraborty7777de92011-09-13 08:06:18 +00001279 struct qlcnic_cmd_args cmd;
Manish Chopraee9e8b62013-05-23 21:04:35 +00001280 u8 pci_func = *arg1 >> 8;
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001281 int err;
Anirban Chakraborty7777de92011-09-13 08:06:18 +00001282
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001283 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1284 QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
1285 if (err)
1286 return err;
1287
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001288 cmd.req.arg[1] = *arg1;
1289 err = qlcnic_issue_cmd(adapter, &cmd);
1290 *arg1 = cmd.rsp.arg[1];
1291 *arg2 = cmd.rsp.arg[2];
1292 qlcnic_free_mbx_args(&cmd);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001293
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001294 if (err == QLCNIC_RCODE_SUCCESS)
Manish Chopraee9e8b62013-05-23 21:04:35 +00001295 dev_info(dev, "Get eSwitch port config for vNIC function %d\n",
1296 pci_func);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001297 else
Manish Chopraee9e8b62013-05-23 21:04:35 +00001298 dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n",
1299 pci_func);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001300 return err;
1301}
1302/* Configure eSwitch port
1303op_mode = 0 for setting default port behavior
1304op_mode = 1 for setting vlan id
1305op_mode = 2 for deleting vlan id
1306op_type = 0 for vlan_id
1307op_type = 1 for port vlan_id
1308*/
1309int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
1310 struct qlcnic_esw_func_cfg *esw_cfg)
1311{
Manish Chopraee9e8b62013-05-23 21:04:35 +00001312 struct device *dev = &adapter->pdev->dev;
1313 struct qlcnic_cmd_args cmd;
Sony Chackobff57d82012-12-04 03:33:56 +00001314 int err = -EIO, index;
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001315 u32 arg1, arg2 = 0;
1316 u8 pci_func;
1317
Sony Chacko79788452012-12-04 03:33:53 +00001318 if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001319 return err;
1320 pci_func = esw_cfg->pci_func;
Sony Chackobff57d82012-12-04 03:33:56 +00001321 index = qlcnic_is_valid_nic_func(adapter, pci_func);
1322 if (index < 0)
1323 return err;
1324 arg1 = (adapter->npars[index].phy_port & BIT_0);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001325 arg1 |= (pci_func << 8);
1326
1327 if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
1328 return err;
1329 arg1 &= ~(0x0ff << 8);
1330 arg1 |= (pci_func << 8);
1331 arg1 &= ~(BIT_2 | BIT_3);
1332 switch (esw_cfg->op_mode) {
1333 case QLCNIC_PORT_DEFAULTS:
1334 arg1 |= (BIT_4 | BIT_6 | BIT_7);
1335 arg2 |= (BIT_0 | BIT_1);
Sony Chacko79788452012-12-04 03:33:53 +00001336 if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001337 arg2 |= (BIT_2 | BIT_3);
1338 if (!(esw_cfg->discard_tagged))
1339 arg1 &= ~BIT_4;
1340 if (!(esw_cfg->promisc_mode))
1341 arg1 &= ~BIT_6;
Rajesh Borundia73733732010-08-31 17:17:50 +00001342 if (!(esw_cfg->mac_override))
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001343 arg1 &= ~BIT_7;
1344 if (!(esw_cfg->mac_anti_spoof))
1345 arg2 &= ~BIT_0;
1346 if (!(esw_cfg->offload_flags & BIT_0))
1347 arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
1348 if (!(esw_cfg->offload_flags & BIT_1))
1349 arg2 &= ~BIT_2;
1350 if (!(esw_cfg->offload_flags & BIT_2))
1351 arg2 &= ~BIT_3;
1352 break;
1353 case QLCNIC_ADD_VLAN:
1354 arg1 |= (BIT_2 | BIT_5);
1355 arg1 |= (esw_cfg->vlan_id << 16);
1356 break;
1357 case QLCNIC_DEL_VLAN:
1358 arg1 |= (BIT_3 | BIT_5);
1359 arg1 &= ~(0x0ffff << 16);
Rajesh Borundiae9a47702010-08-25 04:03:02 +00001360 break;
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001361 default:
1362 return err;
1363 }
1364
Shahed Shaikhb6b43162013-06-22 04:12:00 -04001365 err = qlcnic_alloc_mbx_args(&cmd, adapter,
1366 QLCNIC_CMD_CONFIGURE_ESWITCH);
1367 if (err)
1368 return err;
1369
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001370 cmd.req.arg[1] = arg1;
1371 cmd.req.arg[2] = arg2;
1372 err = qlcnic_issue_cmd(adapter, &cmd);
1373 qlcnic_free_mbx_args(&cmd);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001374
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001375 if (err != QLCNIC_RCODE_SUCCESS)
Manish Chopraee9e8b62013-05-23 21:04:35 +00001376 dev_err(dev, "Failed to configure eswitch for vNIC function %d\n",
1377 pci_func);
Sony Chacko7e2cf4f2013-01-01 03:20:17 +00001378 else
Manish Chopraee9e8b62013-05-23 21:04:35 +00001379 dev_info(dev, "Configured eSwitch for vNIC function %d\n",
1380 pci_func);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001381
1382 return err;
1383}
1384
1385int
1386qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
1387 struct qlcnic_esw_func_cfg *esw_cfg)
1388{
1389 u32 arg1, arg2;
Sony Chackobff57d82012-12-04 03:33:56 +00001390 int index;
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001391 u8 phy_port;
Sony Chackobff57d82012-12-04 03:33:56 +00001392
1393 if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
1394 index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func);
1395 if (index < 0)
1396 return -EIO;
1397 phy_port = adapter->npars[index].phy_port;
1398 } else {
Sony Chacko79788452012-12-04 03:33:53 +00001399 phy_port = adapter->ahw->physical_port;
Sony Chackobff57d82012-12-04 03:33:56 +00001400 }
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001401 arg1 = phy_port;
1402 arg1 |= (esw_cfg->pci_func << 8);
1403 if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
1404 return -EIO;
1405
1406 esw_cfg->discard_tagged = !!(arg1 & BIT_4);
1407 esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
1408 esw_cfg->promisc_mode = !!(arg1 & BIT_6);
Rajesh Borundia73733732010-08-31 17:17:50 +00001409 esw_cfg->mac_override = !!(arg1 & BIT_7);
Rajesh Borundia4e8acb02010-08-19 05:08:25 +00001410 esw_cfg->vlan_id = LSW(arg1 >> 16);
1411 esw_cfg->mac_anti_spoof = (arg2 & 0x1);
1412 esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
1413
1414 return 0;
1415}