blob: b14949a71eda3da4df089eb8e1c6c4de8d55f2a7 [file] [log] [blame]
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301/**
Jayamohan Kallickal533c1652013-04-05 20:38:34 -07002 * Copyright (C) 2005 - 2013 Emulex
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation. The full GNU General
8 * Public License is included in this distribution in the file called COPYING.
9 *
10 * Contact Information:
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070011 * linux-drivers@emulex.com
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053012 *
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070013 * Emulex
14 * 3333 Susan Street
15 * Costa Mesa, CA 92626
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053016 */
17
John Soni Jose21771992012-04-03 23:41:49 -050018#include <scsi/iscsi_proto.h>
19
Jayamohan Kallickal4eea99d2013-09-28 15:35:48 -070020#include "be_main.h"
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053021#include "be.h"
22#include "be_mgmt.h"
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053023
Jayamohan Kallickale9b91192010-07-22 04:24:53 +053024int beiscsi_pci_soft_reset(struct beiscsi_hba *phba)
25{
26 u32 sreset;
27 u8 *pci_reset_offset = 0;
28 u8 *pci_online0_offset = 0;
29 u8 *pci_online1_offset = 0;
30 u32 pconline0 = 0;
31 u32 pconline1 = 0;
32 u32 i;
33
34 pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET;
35 pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0;
36 pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1;
37 sreset = readl((void *)pci_reset_offset);
38 sreset |= BE2_SET_RESET;
39 writel(sreset, (void *)pci_reset_offset);
40
41 i = 0;
42 while (sreset & BE2_SET_RESET) {
43 if (i > 64)
44 break;
45 msleep(100);
46 sreset = readl((void *)pci_reset_offset);
47 i++;
48 }
49
50 if (sreset & BE2_SET_RESET) {
John Soni Jose99bc5d52012-08-20 23:00:18 +053051 printk(KERN_ERR DRV_NAME
52 " Soft Reset did not deassert\n");
Jayamohan Kallickale9b91192010-07-22 04:24:53 +053053 return -EIO;
54 }
55 pconline1 = BE2_MPU_IRAM_ONLINE;
56 writel(pconline0, (void *)pci_online0_offset);
57 writel(pconline1, (void *)pci_online1_offset);
58
Minh Tran1d8bc702012-10-20 04:41:24 +053059 sreset |= BE2_SET_RESET;
Jayamohan Kallickale9b91192010-07-22 04:24:53 +053060 writel(sreset, (void *)pci_reset_offset);
61
62 i = 0;
63 while (sreset & BE2_SET_RESET) {
64 if (i > 64)
65 break;
66 msleep(1);
67 sreset = readl((void *)pci_reset_offset);
68 i++;
69 }
70 if (sreset & BE2_SET_RESET) {
John Soni Jose99bc5d52012-08-20 23:00:18 +053071 printk(KERN_ERR DRV_NAME
72 " MPU Online Soft Reset did not deassert\n");
Jayamohan Kallickale9b91192010-07-22 04:24:53 +053073 return -EIO;
74 }
75 return 0;
76}
77
78int be_chk_reset_complete(struct beiscsi_hba *phba)
79{
80 unsigned int num_loop;
81 u8 *mpu_sem = 0;
82 u32 status;
83
84 num_loop = 1000;
85 mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
86 msleep(5000);
87
88 while (num_loop) {
89 status = readl((void *)mpu_sem);
90
91 if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000)
92 break;
93 msleep(60);
94 num_loop--;
95 }
96
97 if ((status & 0x80000000) || (!num_loop)) {
John Soni Jose99bc5d52012-08-20 23:00:18 +053098 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
99 "BC_%d : Failed in be_chk_reset_complete"
100 "status = 0x%x\n", status);
Jayamohan Kallickale9b91192010-07-22 04:24:53 +0530101 return -EIO;
102 }
103
104 return 0;
105}
106
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530107void be_mcc_notify(struct beiscsi_hba *phba)
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530108{
109 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
110 u32 val = 0;
111
112 val |= mccq->id & DB_MCCQ_RING_ID_MASK;
113 val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
114 iowrite32(val, phba->db_va + DB_MCCQ_OFFSET);
115}
116
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530117unsigned int alloc_mcc_tag(struct beiscsi_hba *phba)
118{
119 unsigned int tag = 0;
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530120
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530121 if (phba->ctrl.mcc_tag_available) {
122 tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index];
123 phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0;
124 phba->ctrl.mcc_numtag[tag] = 0;
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530125 }
126 if (tag) {
127 phba->ctrl.mcc_tag_available--;
128 if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1))
129 phba->ctrl.mcc_alloc_index = 0;
130 else
131 phba->ctrl.mcc_alloc_index++;
132 }
133 return tag;
134}
135
John Soni Josee175def2012-10-20 04:45:40 +0530136/*
137 * beiscsi_mccq_compl()- Wait for completion of MBX
138 * @phba: Driver private structure
139 * @tag: Tag for the MBX Command
140 * @wrb: the WRB used for the MBX Command
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500141 * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd
John Soni Josee175def2012-10-20 04:45:40 +0530142 *
143 * Waits for MBX completion with the passed TAG.
144 *
145 * return
146 * Success: 0
147 * Failure: Non-Zero
148 **/
149int beiscsi_mccq_compl(struct beiscsi_hba *phba,
150 uint32_t tag, struct be_mcc_wrb **wrb,
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500151 struct be_dma_mem *mbx_cmd_mem)
John Soni Josee175def2012-10-20 04:45:40 +0530152{
153 int rc = 0;
154 uint32_t mcc_tag_response;
155 uint16_t status = 0, addl_status = 0, wrb_num = 0;
156 struct be_mcc_wrb *temp_wrb;
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500157 struct be_cmd_req_hdr *mbx_hdr;
158 struct be_cmd_resp_hdr *mbx_resp_hdr;
John Soni Josee175def2012-10-20 04:45:40 +0530159 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
160
Jayamohan Kallickal1f536d42013-09-28 15:35:56 -0700161 if (beiscsi_error(phba)) {
162 free_mcc_tag(&phba->ctrl, tag);
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500163 return -EPERM;
Jayamohan Kallickal1f536d42013-09-28 15:35:56 -0700164 }
John Soni Jose7a158002012-10-20 04:45:51 +0530165
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500166 /* Set MBX Tag state to Active */
167 spin_lock(&phba->ctrl.mbox_lock);
168 phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING;
169 spin_unlock(&phba->ctrl.mbox_lock);
170
John Soni Josee175def2012-10-20 04:45:40 +0530171 /* wait for the mccq completion */
172 rc = wait_event_interruptible_timeout(
173 phba->ctrl.mcc_wait[tag],
174 phba->ctrl.mcc_numtag[tag],
175 msecs_to_jiffies(
176 BEISCSI_HOST_MBX_TIMEOUT));
177
178 if (rc <= 0) {
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500179 struct be_dma_mem *tag_mem;
180 /* Set MBX Tag state to timeout */
181 spin_lock(&phba->ctrl.mbox_lock);
182 phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT;
183 spin_unlock(&phba->ctrl.mbox_lock);
184
185 /* Store resource addr to be freed later */
186 tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state;
187 if (mbx_cmd_mem) {
188 tag_mem->size = mbx_cmd_mem->size;
189 tag_mem->va = mbx_cmd_mem->va;
190 tag_mem->dma = mbx_cmd_mem->dma;
191 } else
192 tag_mem->size = 0;
193
John Soni Josee175def2012-10-20 04:45:40 +0530194 beiscsi_log(phba, KERN_ERR,
195 BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
196 BEISCSI_LOG_CONFIG,
197 "BC_%d : MBX Cmd Completion timed out\n");
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500198 return -EBUSY;
199 } else {
John Soni Josee175def2012-10-20 04:45:40 +0530200 rc = 0;
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500201 /* Set MBX Tag state to completed */
202 spin_lock(&phba->ctrl.mbox_lock);
203 phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED;
204 spin_unlock(&phba->ctrl.mbox_lock);
205 }
John Soni Josee175def2012-10-20 04:45:40 +0530206
207 mcc_tag_response = phba->ctrl.mcc_numtag[tag];
208 status = (mcc_tag_response & CQE_STATUS_MASK);
209 addl_status = ((mcc_tag_response & CQE_STATUS_ADDL_MASK) >>
210 CQE_STATUS_ADDL_SHIFT);
211
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500212 if (mbx_cmd_mem) {
213 mbx_hdr = (struct be_cmd_req_hdr *)mbx_cmd_mem->va;
John Soni Josee175def2012-10-20 04:45:40 +0530214 } else {
215 wrb_num = (mcc_tag_response & CQE_STATUS_WRB_MASK) >>
216 CQE_STATUS_WRB_SHIFT;
217 temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num);
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500218 mbx_hdr = embedded_payload(temp_wrb);
John Soni Josee175def2012-10-20 04:45:40 +0530219
220 if (wrb)
221 *wrb = temp_wrb;
222 }
223
224 if (status || addl_status) {
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500225 beiscsi_log(phba, KERN_WARNING,
John Soni Josee175def2012-10-20 04:45:40 +0530226 BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
227 BEISCSI_LOG_CONFIG,
228 "BC_%d : MBX Cmd Failed for "
229 "Subsys : %d Opcode : %d with "
230 "Status : %d and Extd_Status : %d\n",
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500231 mbx_hdr->subsystem,
232 mbx_hdr->opcode,
John Soni Josee175def2012-10-20 04:45:40 +0530233 status, addl_status);
Jayamohan Kallickala8081e32013-04-05 20:38:22 -0700234
235 if (status == MCC_STATUS_INSUFFICIENT_BUFFER) {
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500236 mbx_resp_hdr = (struct be_cmd_resp_hdr *) mbx_hdr;
Jayamohan Kallickal1f536d42013-09-28 15:35:56 -0700237 beiscsi_log(phba, KERN_WARNING,
238 BEISCSI_LOG_INIT | BEISCSI_LOG_EH |
239 BEISCSI_LOG_CONFIG,
240 "BC_%d : Insufficent Buffer Error "
241 "Resp_Len : %d Actual_Resp_Len : %d\n",
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500242 mbx_resp_hdr->response_length,
243 mbx_resp_hdr->actual_resp_len);
Jayamohan Kallickal1f536d42013-09-28 15:35:56 -0700244
245 rc = -EAGAIN;
246 goto release_mcc_tag;
Jayamohan Kallickala8081e32013-04-05 20:38:22 -0700247 }
Jayamohan Kallickal1f536d42013-09-28 15:35:56 -0700248 rc = -EIO;
John Soni Josee175def2012-10-20 04:45:40 +0530249 }
250
251release_mcc_tag:
252 /* Release the MCC entry */
253 free_mcc_tag(&phba->ctrl, tag);
254
255 return rc;
256}
257
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530258void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag)
259{
260 spin_lock(&ctrl->mbox_lock);
261 tag = tag & 0x000000FF;
262 ctrl->mcc_tag[ctrl->mcc_free_index] = tag;
263 if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1))
264 ctrl->mcc_free_index = 0;
265 else
266 ctrl->mcc_free_index++;
267 ctrl->mcc_tag_available++;
268 spin_unlock(&ctrl->mbox_lock);
269}
270
271bool is_link_state_evt(u32 trailer)
272{
273 return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
274 ASYNC_TRAILER_EVENT_CODE_MASK) ==
275 ASYNC_EVENT_CODE_LINK_STATE);
276}
277
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530278static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
279{
280 if (compl->flags != 0) {
281 compl->flags = le32_to_cpu(compl->flags);
282 WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
283 return true;
284 } else
285 return false;
286}
287
288static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
289{
290 compl->flags = 0;
291}
292
John Soni Josee175def2012-10-20 04:45:40 +0530293/*
294 * be_mcc_compl_process()- Check the MBX comapletion status
295 * @ctrl: Function specific MBX data structure
296 * @compl: Completion status of MBX Command
297 *
298 * Check for the MBX completion status when BMBX method used
299 *
300 * return
301 * Success: Zero
302 * Failure: Non-Zero
303 **/
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530304static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
305 struct be_mcc_compl *compl)
306{
307 u16 compl_status, extd_status;
John Soni Josee175def2012-10-20 04:45:40 +0530308 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
John Soni Jose99bc5d52012-08-20 23:00:18 +0530309 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
John Soni Josee175def2012-10-20 04:45:40 +0530310 struct be_cmd_req_hdr *hdr = embedded_payload(wrb);
Jayamohan Kallickala8081e32013-04-05 20:38:22 -0700311 struct be_cmd_resp_hdr *resp_hdr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530312
313 be_dws_le_to_cpu(compl, 4);
314
315 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
316 CQE_STATUS_COMPL_MASK;
317 if (compl_status != MCC_STATUS_SUCCESS) {
318 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
319 CQE_STATUS_EXTD_MASK;
John Soni Jose99bc5d52012-08-20 23:00:18 +0530320
321 beiscsi_log(phba, KERN_ERR,
322 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
John Soni Josee175def2012-10-20 04:45:40 +0530323 "BC_%d : error in cmd completion: "
324 "Subsystem : %d Opcode : %d "
325 "status(compl/extd)=%d/%d\n",
326 hdr->subsystem, hdr->opcode,
John Soni Jose99bc5d52012-08-20 23:00:18 +0530327 compl_status, extd_status);
328
Jayamohan Kallickala8081e32013-04-05 20:38:22 -0700329 if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) {
330 resp_hdr = (struct be_cmd_resp_hdr *) hdr;
331 if (resp_hdr->response_length)
332 return 0;
333 }
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +0530334 return -EBUSY;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530335 }
336 return 0;
337}
338
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530339int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
340 struct be_mcc_compl *compl)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530341{
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500342 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530343 u16 compl_status, extd_status;
344 unsigned short tag;
345
346 be_dws_le_to_cpu(compl, 4);
347
348 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
349 CQE_STATUS_COMPL_MASK;
350 /* The ctrl.mcc_numtag[tag] is filled with
351 * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status,
352 * [7:0] = compl_status
353 */
354 tag = (compl->tag0 & 0x000000FF);
355 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
356 CQE_STATUS_EXTD_MASK;
357
358 ctrl->mcc_numtag[tag] = 0x80000000;
359 ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000);
360 ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8;
361 ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF);
Jayamohan Kallickal1957aa72014-01-29 02:16:39 -0500362
363 if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_RUNNING) {
364 wake_up_interruptible(&ctrl->mcc_wait[tag]);
365 } else if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_TIMEOUT) {
366 struct be_dma_mem *tag_mem;
367 tag_mem = &ctrl->ptag_state[tag].tag_mem_state;
368
369 beiscsi_log(phba, KERN_WARNING,
370 BEISCSI_LOG_MBOX | BEISCSI_LOG_INIT |
371 BEISCSI_LOG_CONFIG,
372 "BC_%d : MBX Completion for timeout Command "
373 "from FW\n");
374 /* Check if memory needs to be freed */
375 if (tag_mem->size)
376 pci_free_consistent(ctrl->pdev, tag_mem->size,
377 tag_mem->va, tag_mem->dma);
378
379 /* Change tag state */
380 spin_lock(&phba->ctrl.mbox_lock);
381 ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED;
382 spin_unlock(&phba->ctrl.mbox_lock);
383
384 /* Free MCC Tag */
385 free_mcc_tag(ctrl, tag);
386 }
387
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530388 return 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530389}
390
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530391static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba)
392{
393 struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq;
394 struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
395
396 if (be_mcc_compl_is_new(compl)) {
397 queue_tail_inc(mcc_cq);
398 return compl;
399 }
400 return NULL;
401}
402
403static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session)
404{
405 iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
406}
407
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530408void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530409 struct be_async_event_link_state *evt)
410{
Jayamohan Kallickal6ea9b3b2013-04-05 20:38:30 -0700411 if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) ||
412 ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
413 (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) {
414 phba->state = BE_ADAPTER_LINK_DOWN;
415
John Soni Jose99bc5d52012-08-20 23:00:18 +0530416 beiscsi_log(phba, KERN_ERR,
417 BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
Jayamohan Kallickal6ea9b3b2013-04-05 20:38:30 -0700418 "BC_%d : Link Down on Port %d\n",
John Soni Jose99bc5d52012-08-20 23:00:18 +0530419 evt->physical_port);
420
Jayamohan Kallickalda7408c2010-01-05 05:11:23 +0530421 iscsi_host_for_each_session(phba->shost,
422 be2iscsi_fail_session);
Jayamohan Kallickal6ea9b3b2013-04-05 20:38:30 -0700423 } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) ||
424 ((evt->port_link_status & ASYNC_EVENT_LOGICAL) &&
425 (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) {
Jayamohan Kallickal3567f362013-09-28 15:35:58 -0700426 phba->state = BE_ADAPTER_LINK_UP;
Jayamohan Kallickal6ea9b3b2013-04-05 20:38:30 -0700427
John Soni Jose99bc5d52012-08-20 23:00:18 +0530428 beiscsi_log(phba, KERN_ERR,
429 BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT,
Jayamohan Kallickal6ea9b3b2013-04-05 20:38:30 -0700430 "BC_%d : Link UP on Port %d\n",
John Soni Jose99bc5d52012-08-20 23:00:18 +0530431 evt->physical_port);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530432 }
433}
434
435static void beiscsi_cq_notify(struct beiscsi_hba *phba, u16 qid, bool arm,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530436 u16 num_popped)
437{
438 u32 val = 0;
439 val |= qid & DB_CQ_RING_ID_MASK;
440 if (arm)
441 val |= 1 << DB_CQ_REARM_SHIFT;
442 val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530443 iowrite32(val, phba->db_va + DB_CQ_OFFSET);
444}
445
446
Jayamohan Kallickal35e66012009-10-23 11:53:49 +0530447int beiscsi_process_mcc(struct beiscsi_hba *phba)
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530448{
449 struct be_mcc_compl *compl;
450 int num = 0, status = 0;
451 struct be_ctrl_info *ctrl = &phba->ctrl;
452
453 spin_lock_bh(&phba->ctrl.mcc_cq_lock);
454 while ((compl = be_mcc_compl_get(phba))) {
455 if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
456 /* Interpret flags as an async trailer */
Jayamohan Kallickal78b9fb62009-11-25 01:41:37 +0530457 if (is_link_state_evt(compl->flags))
458 /* Interpret compl as a async link evt */
459 beiscsi_async_link_state_process(phba,
460 (struct be_async_event_link_state *) compl);
461 else
John Soni Jose99bc5d52012-08-20 23:00:18 +0530462 beiscsi_log(phba, KERN_ERR,
463 BEISCSI_LOG_CONFIG |
464 BEISCSI_LOG_MBOX,
465 "BC_%d : Unsupported Async Event, flags"
466 " = 0x%08x\n", compl->flags);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530467
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530468 } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
469 status = be_mcc_compl_process(ctrl, compl);
470 atomic_dec(&phba->ctrl.mcc_obj.q.used);
471 }
472 be_mcc_compl_use(compl);
473 num++;
474 }
475
476 if (num)
477 beiscsi_cq_notify(phba, phba->ctrl.mcc_obj.cq.id, true, num);
478
479 spin_unlock_bh(&phba->ctrl.mcc_cq_lock);
480 return status;
481}
482
John Soni Josee175def2012-10-20 04:45:40 +0530483/*
484 * be_mcc_wait_compl()- Wait for MBX completion
485 * @phba: driver private structure
486 *
487 * Wait till no more pending mcc requests are present
488 *
489 * return
490 * Success: 0
491 * Failure: Non-Zero
492 *
493 **/
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530494static int be_mcc_wait_compl(struct beiscsi_hba *phba)
495{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530496 int i, status;
497 for (i = 0; i < mcc_timeout; i++) {
John Soni Jose7a158002012-10-20 04:45:51 +0530498 if (beiscsi_error(phba))
John Soni Josee175def2012-10-20 04:45:40 +0530499 return -EIO;
500
Jayamohan Kallickal35e66012009-10-23 11:53:49 +0530501 status = beiscsi_process_mcc(phba);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530502 if (status)
503 return status;
504
505 if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0)
506 break;
507 udelay(100);
508 }
509 if (i == mcc_timeout) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530510 beiscsi_log(phba, KERN_ERR,
511 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
John Soni Josee175def2012-10-20 04:45:40 +0530512 "BC_%d : FW Timed Out\n");
513 phba->fw_timeout = true;
John Soni Jose7a158002012-10-20 04:45:51 +0530514 beiscsi_ue_detect(phba);
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +0530515 return -EBUSY;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530516 }
517 return 0;
518}
519
John Soni Josee175def2012-10-20 04:45:40 +0530520/*
521 * be_mcc_notify_wait()- Notify and wait for Compl
522 * @phba: driver private structure
523 *
524 * Notify MCC requests and wait for completion
525 *
526 * return
527 * Success: 0
528 * Failure: Non-Zero
529 **/
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530530int be_mcc_notify_wait(struct beiscsi_hba *phba)
531{
532 be_mcc_notify(phba);
533 return be_mcc_wait_compl(phba);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530534}
535
John Soni Josee175def2012-10-20 04:45:40 +0530536/*
537 * be_mbox_db_ready_wait()- Check ready status
538 * @ctrl: Function specific MBX data structure
539 *
540 * Check for the ready status of FW to send BMBX
541 * commands to adapter.
542 *
543 * return
544 * Success: 0
545 * Failure: Non-Zero
546 **/
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530547static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
548{
Jayamohan Kallickal92665a62013-09-28 15:35:43 -0700549#define BEISCSI_MBX_RDY_BIT_TIMEOUT 4000 /* 4sec */
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530550 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
John Soni Josee175def2012-10-20 04:45:40 +0530551 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal92665a62013-09-28 15:35:43 -0700552 unsigned long timeout;
553 bool read_flag = false;
554 int ret = 0, i;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530555 u32 ready;
Jayamohan Kallickal92665a62013-09-28 15:35:43 -0700556 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q);
557
558 if (beiscsi_error(phba))
559 return -EIO;
560
561 timeout = jiffies + (HZ * 110);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530562
563 do {
Jayamohan Kallickal92665a62013-09-28 15:35:43 -0700564 for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) {
565 ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
566 if (ready) {
567 read_flag = true;
568 break;
569 }
570 mdelay(1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530571 }
572
Jayamohan Kallickal92665a62013-09-28 15:35:43 -0700573 if (!read_flag) {
574 wait_event_timeout(rdybit_check_q,
575 (read_flag != true),
576 HZ * 5);
577 }
578 } while ((time_before(jiffies, timeout)) && !read_flag);
579
580 if (!read_flag) {
581 beiscsi_log(phba, KERN_ERR,
582 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
583 "BC_%d : FW Timed Out\n");
584 phba->fw_timeout = true;
585 beiscsi_ue_detect(phba);
586 ret = -EBUSY;
587 }
588
589 return ret;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530590}
591
John Soni Josee175def2012-10-20 04:45:40 +0530592/*
593 * be_mbox_notify: Notify adapter of new BMBX command
594 * @ctrl: Function specific MBX data structure
595 *
596 * Ring doorbell to inform adapter of a BMBX command
597 * to process
598 *
599 * return
600 * Success: 0
601 * Failure: Non-Zero
602 **/
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530603int be_mbox_notify(struct be_ctrl_info *ctrl)
604{
605 int status;
606 u32 val = 0;
607 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
608 struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
609 struct be_mcc_mailbox *mbox = mbox_mem->va;
610 struct be_mcc_compl *compl = &mbox->compl;
John Soni Jose99bc5d52012-08-20 23:00:18 +0530611 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530612
Jayamohan Kallickal1e234bb2013-04-05 20:38:23 -0700613 status = be_mbox_db_ready_wait(ctrl);
614 if (status)
615 return status;
616
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530617 val &= ~MPU_MAILBOX_DB_RDY_MASK;
618 val |= MPU_MAILBOX_DB_HI_MASK;
619 val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
620 iowrite32(val, db);
621
622 status = be_mbox_db_ready_wait(ctrl);
John Soni Josee175def2012-10-20 04:45:40 +0530623 if (status)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530624 return status;
John Soni Josee175def2012-10-20 04:45:40 +0530625
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530626 val = 0;
627 val &= ~MPU_MAILBOX_DB_RDY_MASK;
628 val &= ~MPU_MAILBOX_DB_HI_MASK;
629 val |= (u32) (mbox_mem->dma >> 4) << 2;
630 iowrite32(val, db);
631
632 status = be_mbox_db_ready_wait(ctrl);
John Soni Josee175def2012-10-20 04:45:40 +0530633 if (status)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530634 return status;
John Soni Josee175def2012-10-20 04:45:40 +0530635
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530636 if (be_mcc_compl_is_new(compl)) {
637 status = be_mcc_compl_process(ctrl, &mbox->compl);
638 be_mcc_compl_use(compl);
639 if (status) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530640 beiscsi_log(phba, KERN_ERR,
641 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
642 "BC_%d : After be_mcc_compl_process\n");
643
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530644 return status;
645 }
646 } else {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530647 beiscsi_log(phba, KERN_ERR,
648 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
649 "BC_%d : Invalid Mailbox Completion\n");
650
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +0530651 return -EBUSY;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530652 }
653 return 0;
654}
655
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530656/*
657 * Insert the mailbox address into the doorbell in two steps
658 * Polls on the mbox doorbell till a command completion (or a timeout) occurs
659 */
660static int be_mbox_notify_wait(struct beiscsi_hba *phba)
661{
662 int status;
663 u32 val = 0;
664 void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET;
665 struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem;
666 struct be_mcc_mailbox *mbox = mbox_mem->va;
667 struct be_mcc_compl *compl = &mbox->compl;
668 struct be_ctrl_info *ctrl = &phba->ctrl;
669
Jayamohan Kallickal1e234bb2013-04-05 20:38:23 -0700670 status = be_mbox_db_ready_wait(ctrl);
671 if (status)
672 return status;
673
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530674 val |= MPU_MAILBOX_DB_HI_MASK;
675 /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
676 val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
677 iowrite32(val, db);
678
679 /* wait for ready to be set */
680 status = be_mbox_db_ready_wait(ctrl);
681 if (status != 0)
682 return status;
683
684 val = 0;
685 /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
686 val |= (u32)(mbox_mem->dma >> 4) << 2;
687 iowrite32(val, db);
688
689 status = be_mbox_db_ready_wait(ctrl);
690 if (status != 0)
691 return status;
692
693 /* A cq entry has been made now */
694 if (be_mcc_compl_is_new(compl)) {
695 status = be_mcc_compl_process(ctrl, &mbox->compl);
696 be_mcc_compl_use(compl);
697 if (status)
698 return status;
699 } else {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530700 beiscsi_log(phba, KERN_ERR,
701 BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
702 "BC_%d : invalid mailbox completion\n");
703
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +0530704 return -EBUSY;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530705 }
706 return 0;
707}
708
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530709void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
710 bool embedded, u8 sge_cnt)
711{
712 if (embedded)
713 wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
714 else
715 wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
716 MCC_WRB_SGE_CNT_SHIFT;
717 wrb->payload_length = payload_len;
718 be_dws_cpu_to_le(wrb, 8);
719}
720
721void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
722 u8 subsystem, u8 opcode, int cmd_len)
723{
724 req_hdr->opcode = opcode;
725 req_hdr->subsystem = subsystem;
726 req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
John Soni Josee175def2012-10-20 04:45:40 +0530727 req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530728}
729
730static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
731 struct be_dma_mem *mem)
732{
733 int i, buf_pages;
734 u64 dma = (u64) mem->dma;
735
736 buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
737 for (i = 0; i < buf_pages; i++) {
738 pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
739 pages[i].hi = cpu_to_le32(upper_32_bits(dma));
740 dma += PAGE_SIZE_4K;
741 }
742}
743
744static u32 eq_delay_to_mult(u32 usec_delay)
745{
746#define MAX_INTR_RATE 651042
747 const u32 round = 10;
748 u32 multiplier;
749
750 if (usec_delay == 0)
751 multiplier = 0;
752 else {
753 u32 interrupt_rate = 1000000 / usec_delay;
754 if (interrupt_rate == 0)
755 multiplier = 1023;
756 else {
757 multiplier = (MAX_INTR_RATE - interrupt_rate) * round;
758 multiplier /= interrupt_rate;
759 multiplier = (multiplier + round / 2) / round;
760 multiplier = min(multiplier, (u32) 1023);
761 }
762 }
763 return multiplier;
764}
765
766struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
767{
768 return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
769}
770
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530771struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba)
772{
773 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
774 struct be_mcc_wrb *wrb;
775
Jayamohan Kallickale074d202013-09-28 15:35:39 -0700776 WARN_ON(atomic_read(&mccq->used) >= mccq->len);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530777 wrb = queue_head_node(mccq);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530778 memset(wrb, 0, sizeof(*wrb));
779 wrb->tag0 = (mccq->head & 0x000000FF) << 16;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530780 queue_head_inc(mccq);
781 atomic_inc(&mccq->used);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530782 return wrb;
783}
784
785
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530786int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
787 struct be_queue_info *eq, int eq_delay)
788{
789 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
790 struct be_cmd_req_eq_create *req = embedded_payload(wrb);
791 struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
792 struct be_dma_mem *q_mem = &eq->dma_mem;
793 int status;
794
795 spin_lock(&ctrl->mbox_lock);
796 memset(wrb, 0, sizeof(*wrb));
797
798 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
799
800 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
801 OPCODE_COMMON_EQ_CREATE, sizeof(*req));
802
803 req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
804
805 AMAP_SET_BITS(struct amap_eq_context, func, req->context,
806 PCI_FUNC(ctrl->pdev->devfn));
807 AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
808 AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
809 AMAP_SET_BITS(struct amap_eq_context, count, req->context,
810 __ilog2_u32(eq->len / 256));
811 AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context,
812 eq_delay_to_mult(eq_delay));
813 be_dws_cpu_to_le(req->context, sizeof(req->context));
814
815 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
816
817 status = be_mbox_notify(ctrl);
818 if (!status) {
819 eq->id = le16_to_cpu(resp->eq_id);
820 eq->created = true;
821 }
822 spin_unlock(&ctrl->mbox_lock);
823 return status;
824}
825
Jayamohan Kallickal0283fbb2013-04-05 20:38:21 -0700826/**
827 * be_cmd_fw_initialize()- Initialize FW
828 * @ctrl: Pointer to function control structure
829 *
830 * Send FW initialize pattern for the function.
831 *
832 * return
833 * Success: 0
834 * Failure: Non-Zero value
835 **/
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530836int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
837{
838 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
John Soni Jose99bc5d52012-08-20 23:00:18 +0530839 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530840 int status;
841 u8 *endian_check;
842
843 spin_lock(&ctrl->mbox_lock);
844 memset(wrb, 0, sizeof(*wrb));
845
846 endian_check = (u8 *) wrb;
847 *endian_check++ = 0xFF;
848 *endian_check++ = 0x12;
849 *endian_check++ = 0x34;
850 *endian_check++ = 0xFF;
851 *endian_check++ = 0xFF;
852 *endian_check++ = 0x56;
853 *endian_check++ = 0x78;
854 *endian_check++ = 0xFF;
855 be_dws_cpu_to_le(wrb, sizeof(*wrb));
856
857 status = be_mbox_notify(ctrl);
858 if (status)
John Soni Jose99bc5d52012-08-20 23:00:18 +0530859 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
860 "BC_%d : be_cmd_fw_initialize Failed\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530861
862 spin_unlock(&ctrl->mbox_lock);
863 return status;
864}
865
Jayamohan Kallickal0283fbb2013-04-05 20:38:21 -0700866/**
867 * be_cmd_fw_uninit()- Uinitialize FW
868 * @ctrl: Pointer to function control structure
869 *
870 * Send FW uninitialize pattern for the function
871 *
872 * return
873 * Success: 0
874 * Failure: Non-Zero value
875 **/
876int be_cmd_fw_uninit(struct be_ctrl_info *ctrl)
877{
878 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
879 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
880 int status;
881 u8 *endian_check;
882
883 spin_lock(&ctrl->mbox_lock);
884 memset(wrb, 0, sizeof(*wrb));
885
886 endian_check = (u8 *) wrb;
887 *endian_check++ = 0xFF;
888 *endian_check++ = 0xAA;
889 *endian_check++ = 0xBB;
890 *endian_check++ = 0xFF;
891 *endian_check++ = 0xFF;
892 *endian_check++ = 0xCC;
893 *endian_check++ = 0xDD;
894 *endian_check = 0xFF;
895
896 be_dws_cpu_to_le(wrb, sizeof(*wrb));
897
898 status = be_mbox_notify(ctrl);
899 if (status)
900 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
901 "BC_%d : be_cmd_fw_uninit Failed\n");
902
903 spin_unlock(&ctrl->mbox_lock);
904 return status;
905}
906
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530907int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
908 struct be_queue_info *cq, struct be_queue_info *eq,
909 bool sol_evts, bool no_delay, int coalesce_wm)
910{
911 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
912 struct be_cmd_req_cq_create *req = embedded_payload(wrb);
913 struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
John Soni Jose99bc5d52012-08-20 23:00:18 +0530914 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530915 struct be_dma_mem *q_mem = &cq->dma_mem;
916 void *ctxt = &req->context;
917 int status;
918
919 spin_lock(&ctrl->mbox_lock);
920 memset(wrb, 0, sizeof(*wrb));
921
922 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
923
924 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
925 OPCODE_COMMON_CQ_CREATE, sizeof(*req));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530926
927 req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
Jayamohan Kallickal2c9dfd32013-04-05 20:38:26 -0700928 if (is_chip_be2_be3r(phba)) {
John Soni Joseeaae5262012-10-20 04:43:44 +0530929 AMAP_SET_BITS(struct amap_cq_context, coalescwm,
930 ctxt, coalesce_wm);
931 AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
932 AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
933 __ilog2_u32(cq->len / 256));
934 AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
935 AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
936 AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
937 AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
938 AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
939 AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
940 PCI_FUNC(ctrl->pdev->devfn));
Jayamohan Kallickal2c9dfd32013-04-05 20:38:26 -0700941 } else {
942 req->hdr.version = MBX_CMD_VER2;
943 req->page_size = 1;
944 AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
945 ctxt, coalesce_wm);
946 AMAP_SET_BITS(struct amap_cq_context_v2, nodelay,
947 ctxt, no_delay);
948 AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
949 __ilog2_u32(cq->len / 256));
950 AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1);
951 AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1);
952 AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id);
953 AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1);
John Soni Joseeaae5262012-10-20 04:43:44 +0530954 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530955
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530956 be_dws_cpu_to_le(ctxt, sizeof(req->context));
957
958 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
959
960 status = be_mbox_notify(ctrl);
961 if (!status) {
962 cq->id = le16_to_cpu(resp->cq_id);
963 cq->created = true;
964 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +0530965 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
966 "BC_%d : In be_cmd_cq_create, status=ox%08x\n",
967 status);
968
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530969 spin_unlock(&ctrl->mbox_lock);
970
971 return status;
972}
973
974static u32 be_encoded_q_len(int q_len)
975{
976 u32 len_encoded = fls(q_len); /* log2(len) + 1 */
977 if (len_encoded == 16)
978 len_encoded = 0;
979 return len_encoded;
980}
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530981
Jayamohan Kallickal35e66012009-10-23 11:53:49 +0530982int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba,
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530983 struct be_queue_info *mccq,
984 struct be_queue_info *cq)
985{
986 struct be_mcc_wrb *wrb;
987 struct be_cmd_req_mcc_create *req;
988 struct be_dma_mem *q_mem = &mccq->dma_mem;
989 struct be_ctrl_info *ctrl;
990 void *ctxt;
991 int status;
992
993 spin_lock(&phba->ctrl.mbox_lock);
994 ctrl = &phba->ctrl;
995 wrb = wrb_from_mbox(&ctrl->mbox_mem);
Jayamohan Kallickal37609762011-10-07 19:31:11 -0500996 memset(wrb, 0, sizeof(*wrb));
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530997 req = embedded_payload(wrb);
998 ctxt = &req->context;
999
1000 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1001
1002 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1003 OPCODE_COMMON_MCC_CREATE, sizeof(*req));
1004
1005 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
1006
1007 AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt,
1008 PCI_FUNC(phba->pcidev->devfn));
1009 AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
1010 AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
1011 be_encoded_q_len(mccq->len));
1012 AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id);
1013
1014 be_dws_cpu_to_le(ctxt, sizeof(req->context));
1015
1016 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
1017
1018 status = be_mbox_notify_wait(phba);
1019 if (!status) {
1020 struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
1021 mccq->id = le16_to_cpu(resp->id);
1022 mccq->created = true;
1023 }
1024 spin_unlock(&phba->ctrl.mbox_lock);
1025
1026 return status;
1027}
1028
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301029int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
1030 int queue_type)
1031{
1032 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1033 struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
John Soni Jose99bc5d52012-08-20 23:00:18 +05301034 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301035 u8 subsys = 0, opcode = 0;
1036 int status;
1037
John Soni Jose99bc5d52012-08-20 23:00:18 +05301038 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
1039 "BC_%d : In beiscsi_cmd_q_destroy "
1040 "queue_type : %d\n", queue_type);
1041
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301042 spin_lock(&ctrl->mbox_lock);
1043 memset(wrb, 0, sizeof(*wrb));
1044 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1045
1046 switch (queue_type) {
1047 case QTYPE_EQ:
1048 subsys = CMD_SUBSYSTEM_COMMON;
1049 opcode = OPCODE_COMMON_EQ_DESTROY;
1050 break;
1051 case QTYPE_CQ:
1052 subsys = CMD_SUBSYSTEM_COMMON;
1053 opcode = OPCODE_COMMON_CQ_DESTROY;
1054 break;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301055 case QTYPE_MCCQ:
1056 subsys = CMD_SUBSYSTEM_COMMON;
1057 opcode = OPCODE_COMMON_MCC_DESTROY;
1058 break;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301059 case QTYPE_WRBQ:
1060 subsys = CMD_SUBSYSTEM_ISCSI;
1061 opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY;
1062 break;
1063 case QTYPE_DPDUQ:
1064 subsys = CMD_SUBSYSTEM_ISCSI;
1065 opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY;
1066 break;
1067 case QTYPE_SGL:
1068 subsys = CMD_SUBSYSTEM_ISCSI;
1069 opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES;
1070 break;
1071 default:
1072 spin_unlock(&ctrl->mbox_lock);
1073 BUG();
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +05301074 return -ENXIO;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301075 }
1076 be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
1077 if (queue_type != QTYPE_SGL)
1078 req->id = cpu_to_le16(q->id);
1079
1080 status = be_mbox_notify(ctrl);
1081
1082 spin_unlock(&ctrl->mbox_lock);
1083 return status;
1084}
1085
Jayamohan Kallickal8a86e832013-09-28 15:35:45 -07001086/**
1087 * be_cmd_create_default_pdu_queue()- Create DEFQ for the adapter
1088 * @ctrl: ptr to ctrl_info
1089 * @cq: Completion Queue
1090 * @dq: Default Queue
1091 * @lenght: ring size
1092 * @entry_size: size of each entry in DEFQ
1093 * @is_header: Header or Data DEFQ
1094 * @ulp_num: Bind to which ULP
1095 *
1096 * Create HDR/Data DEFQ for the passed ULP. Unsol PDU are posted
1097 * on this queue by the FW
1098 *
1099 * return
1100 * Success: 0
1101 * Failure: Non-Zero Value
1102 *
1103 **/
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301104int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
1105 struct be_queue_info *cq,
1106 struct be_queue_info *dq, int length,
Jayamohan Kallickal8a86e832013-09-28 15:35:45 -07001107 int entry_size, uint8_t is_header,
1108 uint8_t ulp_num)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301109{
1110 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1111 struct be_defq_create_req *req = embedded_payload(wrb);
1112 struct be_dma_mem *q_mem = &dq->dma_mem;
Jayamohan Kallickalef9e1b92013-04-05 20:38:27 -07001113 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301114 void *ctxt = &req->context;
1115 int status;
1116
1117 spin_lock(&ctrl->mbox_lock);
1118 memset(wrb, 0, sizeof(*wrb));
1119
1120 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1121
1122 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
1123 OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
1124
1125 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
Jayamohan Kallickal8a86e832013-09-28 15:35:45 -07001126 if (phba->fw_config.dual_ulp_aware) {
1127 req->ulp_num = ulp_num;
1128 req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT);
1129 req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT);
1130 }
Jayamohan Kallickalef9e1b92013-04-05 20:38:27 -07001131
1132 if (is_chip_be2_be3r(phba)) {
1133 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1134 rx_pdid, ctxt, 0);
1135 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1136 rx_pdid_valid, ctxt, 1);
1137 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1138 pci_func_id, ctxt, PCI_FUNC(ctrl->pdev->devfn));
1139 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1140 ring_size, ctxt,
1141 be_encoded_q_len(length /
1142 sizeof(struct phys_addr)));
1143 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1144 default_buffer_size, ctxt, entry_size);
1145 AMAP_SET_BITS(struct amap_be_default_pdu_context,
1146 cq_id_recv, ctxt, cq->id);
1147 } else {
1148 AMAP_SET_BITS(struct amap_default_pdu_context_ext,
1149 rx_pdid, ctxt, 0);
1150 AMAP_SET_BITS(struct amap_default_pdu_context_ext,
1151 rx_pdid_valid, ctxt, 1);
1152 AMAP_SET_BITS(struct amap_default_pdu_context_ext,
1153 ring_size, ctxt,
1154 be_encoded_q_len(length /
1155 sizeof(struct phys_addr)));
1156 AMAP_SET_BITS(struct amap_default_pdu_context_ext,
1157 default_buffer_size, ctxt, entry_size);
1158 AMAP_SET_BITS(struct amap_default_pdu_context_ext,
1159 cq_id_recv, ctxt, cq->id);
1160 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301161
1162 be_dws_cpu_to_le(ctxt, sizeof(req->context));
1163
1164 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
1165
1166 status = be_mbox_notify(ctrl);
1167 if (!status) {
Jayamohan Kallickal8a86e832013-09-28 15:35:45 -07001168 struct be_ring *defq_ring;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301169 struct be_defq_create_resp *resp = embedded_payload(wrb);
1170
1171 dq->id = le16_to_cpu(resp->id);
1172 dq->created = true;
Jayamohan Kallickal8a86e832013-09-28 15:35:45 -07001173 if (is_header)
1174 defq_ring = &phba->phwi_ctrlr->default_pdu_hdr[ulp_num];
1175 else
1176 defq_ring = &phba->phwi_ctrlr->
1177 default_pdu_data[ulp_num];
1178
1179 defq_ring->id = dq->id;
1180
1181 if (!phba->fw_config.dual_ulp_aware) {
1182 defq_ring->ulp_num = BEISCSI_ULP0;
1183 defq_ring->doorbell_offset = DB_RXULP0_OFFSET;
1184 } else {
1185 defq_ring->ulp_num = resp->ulp_num;
1186 defq_ring->doorbell_offset = resp->doorbell_offset;
1187 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301188 }
1189 spin_unlock(&ctrl->mbox_lock);
1190
1191 return status;
1192}
1193
Jayamohan Kallickal4eea99d2013-09-28 15:35:48 -07001194/**
1195 * be_cmd_wrbq_create()- Create WRBQ
1196 * @ctrl: ptr to ctrl_info
1197 * @q_mem: memory details for the queue
1198 * @wrbq: queue info
1199 * @pwrb_context: ptr to wrb_context
1200 * @ulp_num: ULP on which the WRBQ is to be created
1201 *
1202 * Create WRBQ on the passed ULP_NUM.
1203 *
1204 **/
1205int be_cmd_wrbq_create(struct be_ctrl_info *ctrl,
1206 struct be_dma_mem *q_mem,
1207 struct be_queue_info *wrbq,
1208 struct hwi_wrb_context *pwrb_context,
1209 uint8_t ulp_num)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301210{
1211 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1212 struct be_wrbq_create_req *req = embedded_payload(wrb);
1213 struct be_wrbq_create_resp *resp = embedded_payload(wrb);
Jayamohan Kallickal4eea99d2013-09-28 15:35:48 -07001214 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301215 int status;
1216
1217 spin_lock(&ctrl->mbox_lock);
1218 memset(wrb, 0, sizeof(*wrb));
1219
1220 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1221
1222 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
1223 OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req));
1224 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
Jayamohan Kallickal4eea99d2013-09-28 15:35:48 -07001225
1226 if (phba->fw_config.dual_ulp_aware) {
1227 req->ulp_num = ulp_num;
1228 req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT);
1229 req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT);
1230 }
1231
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301232 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
1233
1234 status = be_mbox_notify(ctrl);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301235 if (!status) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301236 wrbq->id = le16_to_cpu(resp->cid);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301237 wrbq->created = true;
Jayamohan Kallickal4eea99d2013-09-28 15:35:48 -07001238
1239 pwrb_context->cid = wrbq->id;
1240 if (!phba->fw_config.dual_ulp_aware) {
1241 pwrb_context->doorbell_offset = DB_TXULP0_OFFSET;
1242 pwrb_context->ulp_num = BEISCSI_ULP0;
1243 } else {
1244 pwrb_context->ulp_num = resp->ulp_num;
1245 pwrb_context->doorbell_offset = resp->doorbell_offset;
1246 }
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301247 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301248 spin_unlock(&ctrl->mbox_lock);
1249 return status;
1250}
1251
Jayamohan Kallickal15a90fe2013-09-28 15:35:38 -07001252int be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl,
1253 struct be_dma_mem *q_mem)
1254{
1255 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1256 struct be_post_template_pages_req *req = embedded_payload(wrb);
1257 int status;
1258
1259 spin_lock(&ctrl->mbox_lock);
1260
1261 memset(wrb, 0, sizeof(*wrb));
1262 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1263 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1264 OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS,
1265 sizeof(*req));
1266
1267 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
1268 req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI;
1269 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
1270
1271 status = be_mbox_notify(ctrl);
1272 spin_unlock(&ctrl->mbox_lock);
1273 return status;
1274}
1275
1276int be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl)
1277{
1278 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1279 struct be_remove_template_pages_req *req = embedded_payload(wrb);
1280 int status;
1281
1282 spin_lock(&ctrl->mbox_lock);
1283
1284 memset(wrb, 0, sizeof(*wrb));
1285 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1286 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1287 OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS,
1288 sizeof(*req));
1289
1290 req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI;
1291
1292 status = be_mbox_notify(ctrl);
1293 spin_unlock(&ctrl->mbox_lock);
1294 return status;
1295}
1296
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301297int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
1298 struct be_dma_mem *q_mem,
1299 u32 page_offset, u32 num_pages)
1300{
1301 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1302 struct be_post_sgl_pages_req *req = embedded_payload(wrb);
John Soni Jose99bc5d52012-08-20 23:00:18 +05301303 struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301304 int status;
1305 unsigned int curr_pages;
1306 u32 internal_page_offset = 0;
1307 u32 temp_num_pages = num_pages;
1308
1309 if (num_pages == 0xff)
1310 num_pages = 1;
1311
1312 spin_lock(&ctrl->mbox_lock);
1313 do {
1314 memset(wrb, 0, sizeof(*wrb));
1315 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1316 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
1317 OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES,
1318 sizeof(*req));
1319 curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req,
1320 pages);
1321 req->num_pages = min(num_pages, curr_pages);
1322 req->page_offset = page_offset;
1323 be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem);
1324 q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE);
1325 internal_page_offset += req->num_pages;
1326 page_offset += req->num_pages;
1327 num_pages -= req->num_pages;
1328
1329 if (temp_num_pages == 0xff)
1330 req->num_pages = temp_num_pages;
1331
1332 status = be_mbox_notify(ctrl);
1333 if (status) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05301334 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
1335 "BC_%d : FW CMD to map iscsi frags failed.\n");
1336
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301337 goto error;
1338 }
1339 } while (num_pages > 0);
1340error:
1341 spin_unlock(&ctrl->mbox_lock);
1342 if (status != 0)
1343 beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
1344 return status;
1345}
Jayamohan Kallickale5285862011-10-07 19:31:08 -05001346
1347int beiscsi_cmd_reset_function(struct beiscsi_hba *phba)
1348{
1349 struct be_ctrl_info *ctrl = &phba->ctrl;
1350 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
1351 struct be_post_sgl_pages_req *req = embedded_payload(wrb);
1352 int status;
1353
1354 spin_lock(&ctrl->mbox_lock);
1355
1356 req = embedded_payload(wrb);
1357 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
1358 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
1359 OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
1360 status = be_mbox_notify_wait(phba);
1361
1362 spin_unlock(&ctrl->mbox_lock);
1363 return status;
1364}
John Soni Jose6f722382012-08-20 23:00:43 +05301365
1366/**
1367 * be_cmd_set_vlan()- Configure VLAN paramters on the adapter
1368 * @phba: device priv structure instance
1369 * @vlan_tag: TAG to be set
1370 *
1371 * Set the VLAN_TAG for the adapter or Disable VLAN on adapter
1372 *
1373 * returns
1374 * TAG for the MBX Cmd
1375 * **/
1376int be_cmd_set_vlan(struct beiscsi_hba *phba,
1377 uint16_t vlan_tag)
1378{
1379 unsigned int tag = 0;
1380 struct be_mcc_wrb *wrb;
1381 struct be_cmd_set_vlan_req *req;
1382 struct be_ctrl_info *ctrl = &phba->ctrl;
1383
1384 spin_lock(&ctrl->mbox_lock);
1385 tag = alloc_mcc_tag(phba);
1386 if (!tag) {
1387 spin_unlock(&ctrl->mbox_lock);
1388 return tag;
1389 }
1390
1391 wrb = wrb_from_mccq(phba);
1392 req = embedded_payload(wrb);
1393 wrb->tag0 |= tag;
1394 be_wrb_hdr_prepare(wrb, sizeof(*wrb), true, 0);
1395 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
1396 OPCODE_COMMON_ISCSI_NTWK_SET_VLAN,
1397 sizeof(*req));
1398
1399 req->interface_hndl = phba->interface_handle;
1400 req->vlan_priority = vlan_tag;
1401
1402 be_mcc_notify(phba);
1403 spin_unlock(&ctrl->mbox_lock);
1404
1405 return tag;
1406}