aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi/be_cmds.c
diff options
context:
space:
mode:
authorJayamohan Kallickal <jayamohank@serverengines.com>2009-09-04 22:06:35 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-02 10:50:33 -0400
commit6733b39a1301b0b020bbcbf3295852e93e624cb1 (patch)
tree91f26838b430933f05fff0101dbd81e2b1c6d4e9 /drivers/scsi/be2iscsi/be_cmds.c
parentd74cf7c3e9c4a6a659e0442aafb550b162d15e72 (diff)
[SCSI] be2iscsi: add 10Gbps iSCSI - BladeEngine 2 driver
[v2: fixed up virt_to_bus() issue spotted by sfr] Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: Jayamohan Kallickal <jayamohank@serverengines.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/be2iscsi/be_cmds.c')
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
new file mode 100644
index 000000000000..08007b6e42df
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -0,0 +1,523 @@
1/**
2 * Copyright (C) 2005 - 2009 ServerEngines
3 * 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:
11 * linux-drivers@serverengines.com
12 *
13 * ServerEngines
14 * 209 N. Fair Oaks Ave
15 * Sunnyvale, CA 94085
16 */
17
18#include "be.h"
19#include "be_mgmt.h"
20#include "be_main.h"
21
22static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
23{
24 if (compl->flags != 0) {
25 compl->flags = le32_to_cpu(compl->flags);
26 WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0);
27 return true;
28 } else
29 return false;
30}
31
32static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
33{
34 compl->flags = 0;
35}
36
37static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
38 struct be_mcc_compl *compl)
39{
40 u16 compl_status, extd_status;
41
42 be_dws_le_to_cpu(compl, 4);
43
44 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
45 CQE_STATUS_COMPL_MASK;
46 if (compl_status != MCC_STATUS_SUCCESS) {
47 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
48 CQE_STATUS_EXTD_MASK;
49 dev_err(&ctrl->pdev->dev,
50 "error in cmd completion: status(compl/extd)=%d/%d\n",
51 compl_status, extd_status);
52 return -1;
53 }
54 return 0;
55}
56
57static inline bool is_link_state_evt(u32 trailer)
58{
59 return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
60 ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE);
61}
62
63void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
64 u16 num_popped)
65{
66 u32 val = 0;
67 val |= qid & DB_CQ_RING_ID_MASK;
68 if (arm)
69 val |= 1 << DB_CQ_REARM_SHIFT;
70 val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
71 iowrite32(val, ctrl->db + DB_CQ_OFFSET);
72}
73
74static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
75{
76#define long_delay 2000
77 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
78 int cnt = 0, wait = 5; /* in usecs */
79 u32 ready;
80
81 do {
82 ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
83 if (ready)
84 break;
85
86 if (cnt > 6000000) {
87 dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
88 return -1;
89 }
90
91 if (cnt > 50) {
92 wait = long_delay;
93 mdelay(long_delay / 1000);
94 } else
95 udelay(wait);
96 cnt += wait;
97 } while (true);
98 return 0;
99}
100
101int be_mbox_notify(struct be_ctrl_info *ctrl)
102{
103 int status;
104 u32 val = 0;
105 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
106 struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
107 struct be_mcc_mailbox *mbox = mbox_mem->va;
108 struct be_mcc_compl *compl = &mbox->compl;
109
110 val &= ~MPU_MAILBOX_DB_RDY_MASK;
111 val |= MPU_MAILBOX_DB_HI_MASK;
112 val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
113 iowrite32(val, db);
114
115 status = be_mbox_db_ready_wait(ctrl);
116 if (status != 0) {
117 SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 1\n");
118 return status;
119 }
120 val = 0;
121 val &= ~MPU_MAILBOX_DB_RDY_MASK;
122 val &= ~MPU_MAILBOX_DB_HI_MASK;
123 val |= (u32) (mbox_mem->dma >> 4) << 2;
124 iowrite32(val, db);
125
126 status = be_mbox_db_ready_wait(ctrl);
127 if (status != 0) {
128 SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 2\n");
129 return status;
130 }
131 if (be_mcc_compl_is_new(compl)) {
132 status = be_mcc_compl_process(ctrl, &mbox->compl);
133 be_mcc_compl_use(compl);
134 if (status) {
135 SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process \n");
136 return status;
137 }
138 } else {
139 dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n");
140 return -1;
141 }
142 return 0;
143}
144
145void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
146 bool embedded, u8 sge_cnt)
147{
148 if (embedded)
149 wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
150 else
151 wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
152 MCC_WRB_SGE_CNT_SHIFT;
153 wrb->payload_length = payload_len;
154 be_dws_cpu_to_le(wrb, 8);
155}
156
157void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
158 u8 subsystem, u8 opcode, int cmd_len)
159{
160 req_hdr->opcode = opcode;
161 req_hdr->subsystem = subsystem;
162 req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
163}
164
165static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
166 struct be_dma_mem *mem)
167{
168 int i, buf_pages;
169 u64 dma = (u64) mem->dma;
170
171 buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages);
172 for (i = 0; i < buf_pages; i++) {
173 pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF);
174 pages[i].hi = cpu_to_le32(upper_32_bits(dma));
175 dma += PAGE_SIZE_4K;
176 }
177}
178
179static u32 eq_delay_to_mult(u32 usec_delay)
180{
181#define MAX_INTR_RATE 651042
182 const u32 round = 10;
183 u32 multiplier;
184
185 if (usec_delay == 0)
186 multiplier = 0;
187 else {
188 u32 interrupt_rate = 1000000 / usec_delay;
189 if (interrupt_rate == 0)
190 multiplier = 1023;
191 else {
192 multiplier = (MAX_INTR_RATE - interrupt_rate) * round;
193 multiplier /= interrupt_rate;
194 multiplier = (multiplier + round / 2) / round;
195 multiplier = min(multiplier, (u32) 1023);
196 }
197 }
198 return multiplier;
199}
200
201struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
202{
203 return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
204}
205
206int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
207 struct be_queue_info *eq, int eq_delay)
208{
209 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
210 struct be_cmd_req_eq_create *req = embedded_payload(wrb);
211 struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
212 struct be_dma_mem *q_mem = &eq->dma_mem;
213 int status;
214
215 spin_lock(&ctrl->mbox_lock);
216 memset(wrb, 0, sizeof(*wrb));
217
218 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
219
220 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
221 OPCODE_COMMON_EQ_CREATE, sizeof(*req));
222
223 req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
224
225 AMAP_SET_BITS(struct amap_eq_context, func, req->context,
226 PCI_FUNC(ctrl->pdev->devfn));
227 AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
228 AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
229 AMAP_SET_BITS(struct amap_eq_context, count, req->context,
230 __ilog2_u32(eq->len / 256));
231 AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context,
232 eq_delay_to_mult(eq_delay));
233 be_dws_cpu_to_le(req->context, sizeof(req->context));
234
235 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
236
237 status = be_mbox_notify(ctrl);
238 if (!status) {
239 eq->id = le16_to_cpu(resp->eq_id);
240 eq->created = true;
241 }
242 spin_unlock(&ctrl->mbox_lock);
243 return status;
244}
245
246int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
247{
248 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
249 int status;
250 u8 *endian_check;
251
252 spin_lock(&ctrl->mbox_lock);
253 memset(wrb, 0, sizeof(*wrb));
254
255 endian_check = (u8 *) wrb;
256 *endian_check++ = 0xFF;
257 *endian_check++ = 0x12;
258 *endian_check++ = 0x34;
259 *endian_check++ = 0xFF;
260 *endian_check++ = 0xFF;
261 *endian_check++ = 0x56;
262 *endian_check++ = 0x78;
263 *endian_check++ = 0xFF;
264 be_dws_cpu_to_le(wrb, sizeof(*wrb));
265
266 status = be_mbox_notify(ctrl);
267 if (status)
268 SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed \n");
269
270 spin_unlock(&ctrl->mbox_lock);
271 return status;
272}
273
274int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
275 struct be_queue_info *cq, struct be_queue_info *eq,
276 bool sol_evts, bool no_delay, int coalesce_wm)
277{
278 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
279 struct be_cmd_req_cq_create *req = embedded_payload(wrb);
280 struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
281 struct be_dma_mem *q_mem = &cq->dma_mem;
282 void *ctxt = &req->context;
283 int status;
284
285 spin_lock(&ctrl->mbox_lock);
286 memset(wrb, 0, sizeof(*wrb));
287
288 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
289
290 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
291 OPCODE_COMMON_CQ_CREATE, sizeof(*req));
292
293 if (!q_mem->va)
294 SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n");
295
296 req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
297
298 AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm);
299 AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay);
300 AMAP_SET_BITS(struct amap_cq_context, count, ctxt,
301 __ilog2_u32(cq->len / 256));
302 AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1);
303 AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts);
304 AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
305 AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
306 AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
307 AMAP_SET_BITS(struct amap_cq_context, func, ctxt,
308 PCI_FUNC(ctrl->pdev->devfn));
309 be_dws_cpu_to_le(ctxt, sizeof(req->context));
310
311 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
312
313 status = be_mbox_notify(ctrl);
314 if (!status) {
315 cq->id = le16_to_cpu(resp->cq_id);
316 cq->created = true;
317 } else
318 SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x \n",
319 status);
320 spin_unlock(&ctrl->mbox_lock);
321
322 return status;
323}
324
325static u32 be_encoded_q_len(int q_len)
326{
327 u32 len_encoded = fls(q_len); /* log2(len) + 1 */
328 if (len_encoded == 16)
329 len_encoded = 0;
330 return len_encoded;
331}
332int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
333 int queue_type)
334{
335 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
336 struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
337 u8 subsys = 0, opcode = 0;
338 int status;
339
340 spin_lock(&ctrl->mbox_lock);
341 memset(wrb, 0, sizeof(*wrb));
342 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
343
344 switch (queue_type) {
345 case QTYPE_EQ:
346 subsys = CMD_SUBSYSTEM_COMMON;
347 opcode = OPCODE_COMMON_EQ_DESTROY;
348 break;
349 case QTYPE_CQ:
350 subsys = CMD_SUBSYSTEM_COMMON;
351 opcode = OPCODE_COMMON_CQ_DESTROY;
352 break;
353 case QTYPE_WRBQ:
354 subsys = CMD_SUBSYSTEM_ISCSI;
355 opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY;
356 break;
357 case QTYPE_DPDUQ:
358 subsys = CMD_SUBSYSTEM_ISCSI;
359 opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY;
360 break;
361 case QTYPE_SGL:
362 subsys = CMD_SUBSYSTEM_ISCSI;
363 opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES;
364 break;
365 default:
366 spin_unlock(&ctrl->mbox_lock);
367 BUG();
368 return -1;
369 }
370 be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
371 if (queue_type != QTYPE_SGL)
372 req->id = cpu_to_le16(q->id);
373
374 status = be_mbox_notify(ctrl);
375
376 spin_unlock(&ctrl->mbox_lock);
377 return status;
378}
379
380int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr)
381{
382 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
383 struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb);
384 int status;
385
386 spin_lock(&ctrl->mbox_lock);
387 memset(wrb, 0, sizeof(*wrb));
388 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
389 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
390 OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG,
391 sizeof(*req));
392
393 status = be_mbox_notify(ctrl);
394 if (!status) {
395 struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb);
396
397 memcpy(mac_addr, resp->mac_address, ETH_ALEN);
398 }
399
400 spin_unlock(&ctrl->mbox_lock);
401 return status;
402}
403
404int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
405 struct be_queue_info *cq,
406 struct be_queue_info *dq, int length,
407 int entry_size)
408{
409 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
410 struct be_defq_create_req *req = embedded_payload(wrb);
411 struct be_dma_mem *q_mem = &dq->dma_mem;
412 void *ctxt = &req->context;
413 int status;
414
415 spin_lock(&ctrl->mbox_lock);
416 memset(wrb, 0, sizeof(*wrb));
417
418 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
419
420 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
421 OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req));
422
423 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
424 AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0);
425 AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt,
426 1);
427 AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt,
428 PCI_FUNC(ctrl->pdev->devfn));
429 AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt,
430 be_encoded_q_len(length / sizeof(struct phys_addr)));
431 AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size,
432 ctxt, entry_size);
433 AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt,
434 cq->id);
435
436 be_dws_cpu_to_le(ctxt, sizeof(req->context));
437
438 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
439
440 status = be_mbox_notify(ctrl);
441 if (!status) {
442 struct be_defq_create_resp *resp = embedded_payload(wrb);
443
444 dq->id = le16_to_cpu(resp->id);
445 dq->created = true;
446 }
447 spin_unlock(&ctrl->mbox_lock);
448
449 return status;
450}
451
452int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
453 struct be_queue_info *wrbq)
454{
455 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
456 struct be_wrbq_create_req *req = embedded_payload(wrb);
457 struct be_wrbq_create_resp *resp = embedded_payload(wrb);
458 int status;
459
460 spin_lock(&ctrl->mbox_lock);
461 memset(wrb, 0, sizeof(*wrb));
462
463 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
464
465 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
466 OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req));
467 req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
468 be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
469
470 status = be_mbox_notify(ctrl);
471 if (!status)
472 wrbq->id = le16_to_cpu(resp->cid);
473 spin_unlock(&ctrl->mbox_lock);
474 return status;
475}
476
477int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
478 struct be_dma_mem *q_mem,
479 u32 page_offset, u32 num_pages)
480{
481 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
482 struct be_post_sgl_pages_req *req = embedded_payload(wrb);
483 int status;
484 unsigned int curr_pages;
485 u32 internal_page_offset = 0;
486 u32 temp_num_pages = num_pages;
487
488 if (num_pages == 0xff)
489 num_pages = 1;
490
491 spin_lock(&ctrl->mbox_lock);
492 do {
493 memset(wrb, 0, sizeof(*wrb));
494 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
495 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
496 OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES,
497 sizeof(*req));
498 curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req,
499 pages);
500 req->num_pages = min(num_pages, curr_pages);
501 req->page_offset = page_offset;
502 be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem);
503 q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE);
504 internal_page_offset += req->num_pages;
505 page_offset += req->num_pages;
506 num_pages -= req->num_pages;
507
508 if (temp_num_pages == 0xff)
509 req->num_pages = temp_num_pages;
510
511 status = be_mbox_notify(ctrl);
512 if (status) {
513 SE_DEBUG(DBG_LVL_1,
514 "FW CMD to map iscsi frags failed.\n");
515 goto error;
516 }
517 } while (num_pages > 0);
518error:
519 spin_unlock(&ctrl->mbox_lock);
520 if (status != 0)
521 beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
522 return status;
523}