aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/be2iscsi/Kconfig8
-rw-r--r--drivers/scsi/be2iscsi/Makefile8
-rw-r--r--drivers/scsi/be2iscsi/be.h183
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.c523
-rw-r--r--drivers/scsi/be2iscsi/be_cmds.h877
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c646
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.h75
-rw-r--r--drivers/scsi/be2iscsi/be_main.c3393
-rw-r--r--drivers/scsi/be2iscsi/be_main.h833
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c321
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h249
14 files changed, 7126 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index c233f6fe0fff..db6c47b3ec5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4625,6 +4625,14 @@ F: drivers/ata/
4625F: include/linux/ata.h 4625F: include/linux/ata.h
4626F: include/linux/libata.h 4626F: include/linux/libata.h
4627 4627
4628SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
4629P: Jayamohan Kallickal
4630M: jayamohank@serverengines.com
4631L: linux-scsi@vger.kernel.org
4632W: http://www.serverengines.com
4633S: Supported
4634F: drivers/scsi/be2iscsi/
4635
4628SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER 4636SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
4629M: Sathya Perla <sathyap@serverengines.com> 4637M: Sathya Perla <sathyap@serverengines.com>
4630M: Subbu Seetharaman <subbus@serverengines.com> 4638M: Subbu Seetharaman <subbus@serverengines.com>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index a8ea01b07868..e11cca4c784c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -366,6 +366,7 @@ config ISCSI_TCP
366 366
367source "drivers/scsi/cxgb3i/Kconfig" 367source "drivers/scsi/cxgb3i/Kconfig"
368source "drivers/scsi/bnx2i/Kconfig" 368source "drivers/scsi/bnx2i/Kconfig"
369source "drivers/scsi/be2iscsi/Kconfig"
369 370
370config SGIWD93_SCSI 371config SGIWD93_SCSI
371 tristate "SGI WD93C93 SCSI Driver" 372 tristate "SGI WD93C93 SCSI Driver"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 316f0a1a7986..3ad61db5e3fa 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_SCSI_MVSAS) += mvsas/
131obj-$(CONFIG_PS3_ROM) += ps3rom.o 131obj-$(CONFIG_PS3_ROM) += ps3rom.o
132obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/ 132obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
133obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/ 133obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
134obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
134obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o 135obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
135 136
136obj-$(CONFIG_ARM) += arm/ 137obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig
new file mode 100644
index 000000000000..2952fcd008ea
--- /dev/null
+++ b/drivers/scsi/be2iscsi/Kconfig
@@ -0,0 +1,8 @@
1config BE2ISCSI
2 tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2"
3 depends on PCI && SCSI
4 select SCSI_ISCSI_ATTRS
5
6 help
7 This driver implements the iSCSI functionality for ServerEngines'
8 10Gbps Storage adapter - BladeEngine 2.
diff --git a/drivers/scsi/be2iscsi/Makefile b/drivers/scsi/be2iscsi/Makefile
new file mode 100644
index 000000000000..c11f443e3f83
--- /dev/null
+++ b/drivers/scsi/be2iscsi/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile to build the iSCSI driver for ServerEngine's BladeEngine.
3#
4#
5
6obj-$(CONFIG_BE2ISCSI) += be2iscsi.o
7
8be2iscsi-y := be_iscsi.o be_main.o be_mgmt.o be_cmds.o
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h
new file mode 100644
index 000000000000..b36020dcf012
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be.h
@@ -0,0 +1,183 @@
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#ifndef BEISCSI_H
19#define BEISCSI_H
20
21#include <linux/pci.h>
22#include <linux/if_vlan.h>
23
24#define FW_VER_LEN 32
25
26struct be_dma_mem {
27 void *va;
28 dma_addr_t dma;
29 u32 size;
30};
31
32struct be_queue_info {
33 struct be_dma_mem dma_mem;
34 u16 len;
35 u16 entry_size; /* Size of an element in the queue */
36 u16 id;
37 u16 tail, head;
38 bool created;
39 atomic_t used; /* Number of valid elements in the queue */
40};
41
42static inline u32 MODULO(u16 val, u16 limit)
43{
44 WARN_ON(limit & (limit - 1));
45 return val & (limit - 1);
46}
47
48static inline void index_inc(u16 *index, u16 limit)
49{
50 *index = MODULO((*index + 1), limit);
51}
52
53static inline void *queue_head_node(struct be_queue_info *q)
54{
55 return q->dma_mem.va + q->head * q->entry_size;
56}
57
58static inline void *queue_tail_node(struct be_queue_info *q)
59{
60 return q->dma_mem.va + q->tail * q->entry_size;
61}
62
63static inline void queue_head_inc(struct be_queue_info *q)
64{
65 index_inc(&q->head, q->len);
66}
67
68static inline void queue_tail_inc(struct be_queue_info *q)
69{
70 index_inc(&q->tail, q->len);
71}
72
73/*ISCSI */
74
75struct be_eq_obj {
76 struct be_queue_info q;
77 char desc[32];
78
79 /* Adaptive interrupt coalescing (AIC) info */
80 bool enable_aic;
81 u16 min_eqd; /* in usecs */
82 u16 max_eqd; /* in usecs */
83 u16 cur_eqd; /* in usecs */
84};
85
86struct be_mcc_obj {
87 struct be_queue_info *q;
88 struct be_queue_info *cq;
89};
90
91struct be_ctrl_info {
92 u8 __iomem *csr;
93 u8 __iomem *db; /* Door Bell */
94 u8 __iomem *pcicfg; /* PCI config space */
95 struct pci_dev *pdev;
96
97 /* Mbox used for cmd request/response */
98 spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
99 struct be_dma_mem mbox_mem;
100 /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
101 * is stored for freeing purpose */
102 struct be_dma_mem mbox_mem_alloced;
103
104 /* MCC Rings */
105 struct be_mcc_obj mcc_obj;
106 spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
107 spinlock_t mcc_cq_lock;
108
109 /* MCC Async callback */
110 void (*async_cb) (void *adapter, bool link_up);
111 void *adapter_ctxt;
112};
113
114#include "be_cmds.h"
115
116#define PAGE_SHIFT_4K 12
117#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
118
119/* Returns number of pages spanned by the data starting at the given addr */
120#define PAGES_4K_SPANNED(_address, size) \
121 ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \
122 (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K))
123
124/* Byte offset into the page corresponding to given address */
125#define OFFSET_IN_PAGE(addr) \
126 ((size_t)(addr) & (PAGE_SIZE_4K-1))
127
128/* Returns bit offset within a DWORD of a bitfield */
129#define AMAP_BIT_OFFSET(_struct, field) \
130 (((size_t)&(((_struct *)0)->field))%32)
131
132/* Returns the bit mask of the field that is NOT shifted into location. */
133static inline u32 amap_mask(u32 bitsize)
134{
135 return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1);
136}
137
138static inline void amap_set(void *ptr, u32 dw_offset, u32 mask,
139 u32 offset, u32 value)
140{
141 u32 *dw = (u32 *) ptr + dw_offset;
142 *dw &= ~(mask << offset);
143 *dw |= (mask & value) << offset;
144}
145
146#define AMAP_SET_BITS(_struct, field, ptr, val) \
147 amap_set(ptr, \
148 offsetof(_struct, field)/32, \
149 amap_mask(sizeof(((_struct *)0)->field)), \
150 AMAP_BIT_OFFSET(_struct, field), \
151 val)
152
153static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
154{
155 u32 *dw = ptr;
156 return mask & (*(dw + dw_offset) >> offset);
157}
158
159#define AMAP_GET_BITS(_struct, field, ptr) \
160 amap_get(ptr, \
161 offsetof(_struct, field)/32, \
162 amap_mask(sizeof(((_struct *)0)->field)), \
163 AMAP_BIT_OFFSET(_struct, field))
164
165#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len)
166#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len)
167static inline void swap_dws(void *wrb, int len)
168{
169#ifdef __BIG_ENDIAN
170 u32 *dw = wrb;
171 WARN_ON(len % 4);
172 do {
173 *dw = cpu_to_le32(*dw);
174 dw++;
175 len -= 4;
176 } while (len);
177#endif /* __BIG_ENDIAN */
178}
179
180extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
181 u16 num_popped);
182
183#endif /* BEISCSI_H */
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}
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
new file mode 100644
index 000000000000..c20d686cbb43
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -0,0 +1,877 @@
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#ifndef BEISCSI_CMDS_H
19#define BEISCSI_CMDS_H
20
21/**
22 * The driver sends configuration and managements command requests to the
23 * firmware in the BE. These requests are communicated to the processor
24 * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one
25 * WRB inside a MAILBOX.
26 * The commands are serviced by the ARM processor in the BladeEngine's MPU.
27 */
28struct be_sge {
29 u32 pa_lo;
30 u32 pa_hi;
31 u32 len;
32};
33
34#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */
35#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */
36struct be_mcc_wrb {
37 u32 embedded; /* dword 0 */
38 u32 payload_length; /* dword 1 */
39 u32 tag0; /* dword 2 */
40 u32 tag1; /* dword 3 */
41 u32 rsvd; /* dword 4 */
42 union {
43 u8 embedded_payload[236]; /* used by embedded cmds */
44 struct be_sge sgl[19]; /* used by non-embedded cmds */
45 } payload;
46};
47
48#define CQE_FLAGS_VALID_MASK (1 << 31)
49#define CQE_FLAGS_ASYNC_MASK (1 << 30)
50
51/* Completion Status */
52#define MCC_STATUS_SUCCESS 0x0
53
54#define CQE_STATUS_COMPL_MASK 0xFFFF
55#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
56#define CQE_STATUS_EXTD_MASK 0xFFFF
57#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */
58
59struct be_mcc_compl {
60 u32 status; /* dword 0 */
61 u32 tag0; /* dword 1 */
62 u32 tag1; /* dword 2 */
63 u32 flags; /* dword 3 */
64};
65
66/********* Mailbox door bell *************/
67/**
68 * Used for driver communication with the FW.
69 * The software must write this register twice to post any command. First,
70 * it writes the register with hi=1 and the upper bits of the physical address
71 * for the MAILBOX structure. Software must poll the ready bit until this
72 * is acknowledged. Then, sotware writes the register with hi=0 with the lower
73 * bits in the address. It must poll the ready bit until the command is
74 * complete. Upon completion, the MAILBOX will contain a valid completion
75 * queue entry.
76 */
77#define MPU_MAILBOX_DB_OFFSET 0x160
78#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */
79#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */
80
81/********** MPU semphore ******************/
82#define MPU_EP_SEMAPHORE_OFFSET 0xac
83#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
84#define EP_SEMAPHORE_POST_ERR_MASK 0x1
85#define EP_SEMAPHORE_POST_ERR_SHIFT 31
86
87/********** MCC door bell ************/
88#define DB_MCCQ_OFFSET 0x140
89#define DB_MCCQ_RING_ID_MASK 0x7FF /* bits 0 - 10 */
90/* Number of entries posted */
91#define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */
92
93/* MPU semphore POST stage values */
94#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */
95
96/**
97 * When the async bit of mcc_compl is set, the last 4 bytes of
98 * mcc_compl is interpreted as follows:
99 */
100#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
101#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
102#define ASYNC_EVENT_CODE_LINK_STATE 0x1
103struct be_async_event_trailer {
104 u32 code;
105};
106
107enum {
108 ASYNC_EVENT_LINK_DOWN = 0x0,
109 ASYNC_EVENT_LINK_UP = 0x1
110};
111
112/**
113 * When the event code of an async trailer is link-state, the mcc_compl
114 * must be interpreted as follows
115 */
116struct be_async_event_link_state {
117 u8 physical_port;
118 u8 port_link_status;
119 u8 port_duplex;
120 u8 port_speed;
121 u8 port_fault;
122 u8 rsvd0[7];
123 struct be_async_event_trailer trailer;
124} __packed;
125
126struct be_mcc_mailbox {
127 struct be_mcc_wrb wrb;
128 struct be_mcc_compl compl;
129};
130
131/* Type of subsystems supported by FW */
132#define CMD_SUBSYSTEM_COMMON 0x1
133#define CMD_SUBSYSTEM_ISCSI 0x2
134#define CMD_SUBSYSTEM_ETH 0x3
135#define CMD_SUBSYSTEM_ISCSI_INI 0x6
136#define CMD_COMMON_TCP_UPLOAD 0x1
137
138/**
139 * List of common opcodes subsystem CMD_SUBSYSTEM_COMMON
140 * These opcodes are unique for each subsystem defined above
141 */
142#define OPCODE_COMMON_CQ_CREATE 12
143#define OPCODE_COMMON_EQ_CREATE 13
144#define OPCODE_COMMON_MCC_CREATE 21
145#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32
146#define OPCODE_COMMON_GET_FW_VERSION 35
147#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
148#define OPCODE_COMMON_FIRMWARE_CONFIG 42
149#define OPCODE_COMMON_MCC_DESTROY 53
150#define OPCODE_COMMON_CQ_DESTROY 54
151#define OPCODE_COMMON_EQ_DESTROY 55
152#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
153#define OPCODE_COMMON_FUNCTION_RESET 61
154
155/**
156 * LIST of opcodes that are common between Initiator and Target
157 * used by CMD_SUBSYSTEM_ISCSI
158 * These opcodes are unique for each subsystem defined above
159 */
160#define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2
161#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3
162#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7
163#define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61
164#define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64
165#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65
166#define OPCODE_COMMON_ISCSI_WRBQ_CREATE 66
167#define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67
168
169struct be_cmd_req_hdr {
170 u8 opcode; /* dword 0 */
171 u8 subsystem; /* dword 0 */
172 u8 port_number; /* dword 0 */
173 u8 domain; /* dword 0 */
174 u32 timeout; /* dword 1 */
175 u32 request_length; /* dword 2 */
176 u32 rsvd; /* dword 3 */
177};
178
179struct be_cmd_resp_hdr {
180 u32 info; /* dword 0 */
181 u32 status; /* dword 1 */
182 u32 response_length; /* dword 2 */
183 u32 actual_resp_len; /* dword 3 */
184};
185
186struct phys_addr {
187 u32 lo;
188 u32 hi;
189};
190
191/**************************
192 * BE Command definitions *
193 **************************/
194
195/**
196 * Pseudo amap definition in which each bit of the actual structure is defined
197 * as a byte - used to calculate offset/shift/mask of each field
198 */
199struct amap_eq_context {
200 u8 cidx[13]; /* dword 0 */
201 u8 rsvd0[3]; /* dword 0 */
202 u8 epidx[13]; /* dword 0 */
203 u8 valid; /* dword 0 */
204 u8 rsvd1; /* dword 0 */
205 u8 size; /* dword 0 */
206 u8 pidx[13]; /* dword 1 */
207 u8 rsvd2[3]; /* dword 1 */
208 u8 pd[10]; /* dword 1 */
209 u8 count[3]; /* dword 1 */
210 u8 solevent; /* dword 1 */
211 u8 stalled; /* dword 1 */
212 u8 armed; /* dword 1 */
213 u8 rsvd3[4]; /* dword 2 */
214 u8 func[8]; /* dword 2 */
215 u8 rsvd4; /* dword 2 */
216 u8 delaymult[10]; /* dword 2 */
217 u8 rsvd5[2]; /* dword 2 */
218 u8 phase[2]; /* dword 2 */
219 u8 nodelay; /* dword 2 */
220 u8 rsvd6[4]; /* dword 2 */
221 u8 rsvd7[32]; /* dword 3 */
222} __packed;
223
224struct be_cmd_req_eq_create {
225 struct be_cmd_req_hdr hdr; /* dw[4] */
226 u16 num_pages; /* sword */
227 u16 rsvd0; /* sword */
228 u8 context[sizeof(struct amap_eq_context) / 8]; /* dw[4] */
229 struct phys_addr pages[8];
230} __packed;
231
232struct be_cmd_resp_eq_create {
233 struct be_cmd_resp_hdr resp_hdr;
234 u16 eq_id; /* sword */
235 u16 rsvd0; /* sword */
236} __packed;
237
238struct mac_addr {
239 u16 size_of_struct;
240 u8 addr[ETH_ALEN];
241} __packed;
242
243struct be_cmd_req_mac_query {
244 struct be_cmd_req_hdr hdr;
245 u8 type;
246 u8 permanent;
247 u16 if_id;
248} __packed;
249
250struct be_cmd_resp_mac_query {
251 struct be_cmd_resp_hdr hdr;
252 struct mac_addr mac;
253};
254
255/******************** Create CQ ***************************/
256/**
257 * Pseudo amap definition in which each bit of the actual structure is defined
258 * as a byte - used to calculate offset/shift/mask of each field
259 */
260struct amap_cq_context {
261 u8 cidx[11]; /* dword 0 */
262 u8 rsvd0; /* dword 0 */
263 u8 coalescwm[2]; /* dword 0 */
264 u8 nodelay; /* dword 0 */
265 u8 epidx[11]; /* dword 0 */
266 u8 rsvd1; /* dword 0 */
267 u8 count[2]; /* dword 0 */
268 u8 valid; /* dword 0 */
269 u8 solevent; /* dword 0 */
270 u8 eventable; /* dword 0 */
271 u8 pidx[11]; /* dword 1 */
272 u8 rsvd2; /* dword 1 */
273 u8 pd[10]; /* dword 1 */
274 u8 eqid[8]; /* dword 1 */
275 u8 stalled; /* dword 1 */
276 u8 armed; /* dword 1 */
277 u8 rsvd3[4]; /* dword 2 */
278 u8 func[8]; /* dword 2 */
279 u8 rsvd4[20]; /* dword 2 */
280 u8 rsvd5[32]; /* dword 3 */
281} __packed;
282
283struct be_cmd_req_cq_create {
284 struct be_cmd_req_hdr hdr;
285 u16 num_pages;
286 u16 rsvd0;
287 u8 context[sizeof(struct amap_cq_context) / 8];
288 struct phys_addr pages[4];
289} __packed;
290
291struct be_cmd_resp_cq_create {
292 struct be_cmd_resp_hdr hdr;
293 u16 cq_id;
294 u16 rsvd0;
295} __packed;
296
297/******************** Create MCCQ ***************************/
298/**
299 * Pseudo amap definition in which each bit of the actual structure is defined
300 * as a byte - used to calculate offset/shift/mask of each field
301 */
302struct amap_mcc_context {
303 u8 con_index[14];
304 u8 rsvd0[2];
305 u8 ring_size[4];
306 u8 fetch_wrb;
307 u8 fetch_r2t;
308 u8 cq_id[10];
309 u8 prod_index[14];
310 u8 fid[8];
311 u8 pdid[9];
312 u8 valid;
313 u8 rsvd1[32];
314 u8 rsvd2[32];
315} __packed;
316
317struct be_cmd_req_mcc_create {
318 struct be_cmd_req_hdr hdr;
319 u16 num_pages;
320 u16 rsvd0;
321 u8 context[sizeof(struct amap_mcc_context) / 8];
322 struct phys_addr pages[8];
323} __packed;
324
325struct be_cmd_resp_mcc_create {
326 struct be_cmd_resp_hdr hdr;
327 u16 id;
328 u16 rsvd0;
329} __packed;
330
331/******************** Q Destroy ***************************/
332/* Type of Queue to be destroyed */
333enum {
334 QTYPE_EQ = 1,
335 QTYPE_CQ,
336 QTYPE_MCCQ,
337 QTYPE_WRBQ,
338 QTYPE_DPDUQ,
339 QTYPE_SGL
340};
341
342struct be_cmd_req_q_destroy {
343 struct be_cmd_req_hdr hdr;
344 u16 id;
345 u16 bypass_flush; /* valid only for rx q destroy */
346} __packed;
347
348struct macaddr {
349 u8 byte[ETH_ALEN];
350};
351
352struct be_cmd_req_mcast_mac_config {
353 struct be_cmd_req_hdr hdr;
354 u16 num_mac;
355 u8 promiscuous;
356 u8 interface_id;
357 struct macaddr mac[32];
358} __packed;
359
360static inline void *embedded_payload(struct be_mcc_wrb *wrb)
361{
362 return wrb->payload.embedded_payload;
363}
364
365static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
366{
367 return &wrb->payload.sgl[0];
368}
369
370/******************** Modify EQ Delay *******************/
371struct be_cmd_req_modify_eq_delay {
372 struct be_cmd_req_hdr hdr;
373 u32 num_eq;
374 struct {
375 u32 eq_id;
376 u32 phase;
377 u32 delay_multiplier;
378 } delay[8];
379} __packed;
380
381/******************** Get MAC ADDR *******************/
382
383#define ETH_ALEN 6
384
385
386struct be_cmd_req_get_mac_addr {
387 struct be_cmd_req_hdr hdr;
388 u32 nic_port_count;
389 u32 speed;
390 u32 max_speed;
391 u32 link_state;
392 u32 max_frame_size;
393 u16 size_of_structure;
394 u8 mac_address[ETH_ALEN];
395 u32 rsvd[23];
396};
397
398struct be_cmd_resp_get_mac_addr {
399 struct be_cmd_resp_hdr hdr;
400 u32 nic_port_count;
401 u32 speed;
402 u32 max_speed;
403 u32 link_state;
404 u32 max_frame_size;
405 u16 size_of_structure;
406 u8 mac_address[6];
407 u32 rsvd[23];
408};
409
410int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
411 struct be_queue_info *eq, int eq_delay);
412
413int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
414 struct be_queue_info *cq, struct be_queue_info *eq,
415 bool sol_evts, bool no_delay,
416 int num_cqe_dma_coalesce);
417
418int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
419 int type);
420int be_poll_mcc(struct be_ctrl_info *ctrl);
421unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl);
422int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr);
423
424/*ISCSI Functuions */
425int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
426
427struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
428
429int be_mbox_notify(struct be_ctrl_info *ctrl);
430
431int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl,
432 struct be_queue_info *cq,
433 struct be_queue_info *dq, int length,
434 int entry_size);
435
436int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
437 struct be_dma_mem *q_mem, u32 page_offset,
438 u32 num_pages);
439
440int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
441 struct be_queue_info *wrbq);
442
443struct be_default_pdu_context {
444 u32 dw[4];
445} __packed;
446
447struct amap_be_default_pdu_context {
448 u8 dbuf_cindex[13]; /* dword 0 */
449 u8 rsvd0[3]; /* dword 0 */
450 u8 ring_size[4]; /* dword 0 */
451 u8 ring_state[4]; /* dword 0 */
452 u8 rsvd1[8]; /* dword 0 */
453 u8 dbuf_pindex[13]; /* dword 1 */
454 u8 rsvd2; /* dword 1 */
455 u8 pci_func_id[8]; /* dword 1 */
456 u8 rx_pdid[9]; /* dword 1 */
457 u8 rx_pdid_valid; /* dword 1 */
458 u8 default_buffer_size[16]; /* dword 2 */
459 u8 cq_id_recv[10]; /* dword 2 */
460 u8 rx_pdid_not_valid; /* dword 2 */
461 u8 rsvd3[5]; /* dword 2 */
462 u8 rsvd4[32]; /* dword 3 */
463} __packed;
464
465struct be_defq_create_req {
466 struct be_cmd_req_hdr hdr;
467 u16 num_pages;
468 u8 ulp_num;
469 u8 rsvd0;
470 struct be_default_pdu_context context;
471 struct phys_addr pages[8];
472} __packed;
473
474struct be_defq_create_resp {
475 struct be_cmd_req_hdr hdr;
476 u16 id;
477 u16 rsvd0;
478} __packed;
479
480struct be_post_sgl_pages_req {
481 struct be_cmd_req_hdr hdr;
482 u16 num_pages;
483 u16 page_offset;
484 u32 rsvd0;
485 struct phys_addr pages[26];
486 u32 rsvd1;
487} __packed;
488
489struct be_wrbq_create_req {
490 struct be_cmd_req_hdr hdr;
491 u16 num_pages;
492 u8 ulp_num;
493 u8 rsvd0;
494 struct phys_addr pages[8];
495} __packed;
496
497struct be_wrbq_create_resp {
498 struct be_cmd_resp_hdr resp_hdr;
499 u16 cid;
500 u16 rsvd0;
501} __packed;
502
503#define SOL_CID_MASK 0x0000FFC0
504#define SOL_CODE_MASK 0x0000003F
505#define SOL_WRB_INDEX_MASK 0x00FF0000
506#define SOL_CMD_WND_MASK 0xFF000000
507#define SOL_RES_CNT_MASK 0x7FFFFFFF
508#define SOL_EXP_CMD_SN_MASK 0xFFFFFFFF
509#define SOL_HW_STS_MASK 0x000000FF
510#define SOL_STS_MASK 0x0000FF00
511#define SOL_RESP_MASK 0x00FF0000
512#define SOL_FLAGS_MASK 0x7F000000
513#define SOL_S_MASK 0x80000000
514
515struct sol_cqe {
516 u32 dw[4];
517};
518
519struct amap_sol_cqe {
520 u8 hw_sts[8]; /* dword 0 */
521 u8 i_sts[8]; /* dword 0 */
522 u8 i_resp[8]; /* dword 0 */
523 u8 i_flags[7]; /* dword 0 */
524 u8 s; /* dword 0 */
525 u8 i_exp_cmd_sn[32]; /* dword 1 */
526 u8 code[6]; /* dword 2 */
527 u8 cid[10]; /* dword 2 */
528 u8 wrb_index[8]; /* dword 2 */
529 u8 i_cmd_wnd[8]; /* dword 2 */
530 u8 i_res_cnt[31]; /* dword 3 */
531 u8 valid; /* dword 3 */
532} __packed;
533
534
535/**
536 * Post WRB Queue Doorbell Register used by the host Storage
537 * stack to notify the
538 * controller of a posted Work Request Block
539 */
540#define DB_WRB_POST_CID_MASK 0x3FF /* bits 0 - 9 */
541#define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */
542
543#define DB_DEF_PDU_WRB_INDEX_SHIFT 16
544#define DB_DEF_PDU_NUM_POSTED_SHIFT 24
545
546struct fragnum_bits_for_sgl_cra_in {
547 struct be_cmd_req_hdr hdr;
548 u32 num_bits;
549} __packed;
550
551struct iscsi_cleanup_req {
552 struct be_cmd_req_hdr hdr;
553 u16 chute;
554 u8 hdr_ring_id;
555 u8 data_ring_id;
556
557} __packed;
558
559struct eq_delay {
560 u32 eq_id;
561 u32 phase;
562 u32 delay_multiplier;
563} __packed;
564
565struct be_eq_delay_params_in {
566 struct be_cmd_req_hdr hdr;
567 u32 num_eq;
568 struct eq_delay delay[8];
569} __packed;
570
571struct ip_address_format {
572 u16 size_of_structure;
573 u8 reserved;
574 u8 ip_type;
575 u8 ip_address[16];
576 u32 rsvd0;
577} __packed;
578
579struct tcp_connect_and_offload_in {
580 struct be_cmd_req_hdr hdr;
581 struct ip_address_format ip_address;
582 u16 tcp_port;
583 u16 cid;
584 u16 cq_id;
585 u16 defq_id;
586 struct phys_addr dataout_template_pa;
587 u16 hdr_ring_id;
588 u16 data_ring_id;
589 u8 do_offload;
590 u8 rsvd0[3];
591} __packed;
592
593struct tcp_connect_and_offload_out {
594 struct be_cmd_resp_hdr hdr;
595 u32 connection_handle;
596 u16 cid;
597 u16 rsvd0;
598
599} __packed;
600
601struct be_mcc_wrb_context {
602 struct MCC_WRB *wrb;
603 int *users_final_status;
604} __packed;
605
606#define DB_DEF_PDU_RING_ID_MASK 0x3FF /* bits 0 - 9 */
607#define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 0 - 9 */
608#define DB_DEF_PDU_REARM_SHIFT 14
609#define DB_DEF_PDU_EVENT_SHIFT 15
610#define DB_DEF_PDU_CQPROC_SHIFT 16
611
612struct dmsg_cqe {
613 u32 dw[4];
614} __packed;
615
616struct tcp_upload_params_in {
617 struct be_cmd_req_hdr hdr;
618 u16 id;
619 u16 upload_type;
620 u32 reset_seq;
621} __packed;
622
623struct tcp_upload_params_out {
624 u32 dw[32];
625} __packed;
626
627union tcp_upload_params {
628 struct tcp_upload_params_in request;
629 struct tcp_upload_params_out response;
630} __packed;
631
632struct be_ulp_fw_cfg {
633 u32 ulp_mode;
634 u32 etx_base;
635 u32 etx_count;
636 u32 sq_base;
637 u32 sq_count;
638 u32 rq_base;
639 u32 rq_count;
640 u32 dq_base;
641 u32 dq_count;
642 u32 lro_base;
643 u32 lro_count;
644 u32 icd_base;
645 u32 icd_count;
646};
647
648struct be_fw_cfg {
649 struct be_cmd_req_hdr hdr;
650 u32 be_config_number;
651 u32 asic_revision;
652 u32 phys_port;
653 u32 function_mode;
654 struct be_ulp_fw_cfg ulp[2];
655 u32 function_caps;
656} __packed;
657
658#define CMD_ISCSI_COMMAND_INVALIDATE 1
659#define ISCSI_OPCODE_SCSI_DATA_OUT 5
660#define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70
661#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
662#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
663#define OPCODE_COMMON_ISCSI_CLEANUP 59
664#define OPCODE_COMMON_TCP_UPLOAD 56
665#define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
666/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
667#define CMD_ISCSI_CONNECTION_INVALIDATE 1
668#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2
669#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
670
671#define INI_WR_CMD 1 /* Initiator write command */
672#define INI_TMF_CMD 2 /* Initiator TMF command */
673#define INI_NOPOUT_CMD 3 /* Initiator; Send a NOP-OUT */
674#define INI_RD_CMD 5 /* Initiator requesting to send
675 * a read command
676 */
677#define TGT_CTX_UPDT_CMD 7 /* Target context update */
678#define TGT_STS_CMD 8 /* Target R2T and other BHS
679 * where only the status number
680 * need to be updated
681 */
682#define TGT_DATAIN_CMD 9 /* Target Data-Ins in response
683 * to read command
684 */
685#define TGT_SOS_PDU 10 /* Target:standalone status
686 * response
687 */
688#define TGT_DM_CMD 11 /* Indicates that the bhs
689 * preparedby
690 * driver should not be touched
691 */
692/* --- CMD_CHUTE_TYPE --- */
693#define CMD_CONNECTION_CHUTE_0 1
694#define CMD_CONNECTION_CHUTE_1 2
695#define CMD_CONNECTION_CHUTE_2 3
696
697#define EQ_MAJOR_CODE_COMPLETION 0
698
699#define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0
700#define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1
701
702/* --- CONNECTION_UPLOAD_PARAMS --- */
703/* These parameters are used to define the type of upload desired. */
704#define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */
705#define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with
706 * reset
707 */
708#define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without
709 * reset
710 */
711#define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset,
712 * sequence number by driver */
713
714/* Returns byte size of given field with a structure. */
715
716/* Returns the number of items in the field array. */
717#define BE_NUMBER_OF_FIELD(_type_, _field_) \
718 (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
719
720/**
721 * Different types of iSCSI completions to host driver for both initiator
722 * and taget mode
723 * of operation.
724 */
725#define SOL_CMD_COMPLETE 1 /* Solicited command completed
726 * normally
727 */
728#define SOL_CMD_KILLED_DATA_DIGEST_ERR 2 /* Solicited command got
729 * invalidated internally due
730 * to Data Digest error
731 */
732#define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3 /* Connection got invalidated
733 * internally
734 * due to a recieved PDU
735 * size > DSL
736 */
737#define CXN_KILLED_BURST_LEN_MISMATCH 4 /* Connection got invalidated
738 * internally due ti received
739 * PDU sequence size >
740 * FBL/MBL.
741 */
742#define CXN_KILLED_AHS_RCVD 5 /* Connection got invalidated
743 * internally due to a recieved
744 * PDU Hdr that has
745 * AHS */
746#define CXN_KILLED_HDR_DIGEST_ERR 6 /* Connection got invalidated
747 * internally due to Hdr Digest
748 * error
749 */
750#define CXN_KILLED_UNKNOWN_HDR 7 /* Connection got invalidated
751 * internally
752 * due to a bad opcode in the
753 * pdu hdr
754 */
755#define CXN_KILLED_STALE_ITT_TTT_RCVD 8 /* Connection got invalidated
756 * internally due to a recieved
757 * ITT/TTT that does not belong
758 * to this Connection
759 */
760#define CXN_KILLED_INVALID_ITT_TTT_RCVD 9 /* Connection got invalidated
761 * internally due to recieved
762 * ITT/TTT value > Max
763 * Supported ITTs/TTTs
764 */
765#define CXN_KILLED_RST_RCVD 10 /* Connection got invalidated
766 * internally due to an
767 * incoming TCP RST
768 */
769#define CXN_KILLED_TIMED_OUT 11 /* Connection got invalidated
770 * internally due to timeout on
771 * tcp segment 12 retransmit
772 * attempts failed
773 */
774#define CXN_KILLED_RST_SENT 12 /* Connection got invalidated
775 * internally due to TCP RST
776 * sent by the Tx side
777 */
778#define CXN_KILLED_FIN_RCVD 13 /* Connection got invalidated
779 * internally due to an
780 * incoming TCP FIN.
781 */
782#define CXN_KILLED_BAD_UNSOL_PDU_RCVD 14 /* Connection got invalidated
783 * internally due to bad
784 * unsolicited PDU Unsolicited
785 * PDUs are PDUs with
786 * ITT=0xffffffff
787 */
788#define CXN_KILLED_BAD_WRB_INDEX_ERROR 15 /* Connection got invalidated
789 * internally due to bad WRB
790 * index.
791 */
792#define CXN_KILLED_OVER_RUN_RESIDUAL 16 /* Command got invalidated
793 * internally due to recived
794 * command has residual
795 * over run bytes.
796 */
797#define CXN_KILLED_UNDER_RUN_RESIDUAL 17 /* Command got invalidated
798 * internally due to recived
799 * command has residual under
800 * run bytes.
801 */
802#define CMD_KILLED_INVALID_STATSN_RCVD 18 /* Command got invalidated
803 * internally due to a recieved
804 * PDU has an invalid StatusSN
805 */
806#define CMD_KILLED_INVALID_R2T_RCVD 19 /* Command got invalidated
807 * internally due to a recieved
808 * an R2T with some invalid
809 * fields in it
810 */
811#define CMD_CXN_KILLED_LUN_INVALID 20 /* Command got invalidated
812 * internally due to received
813 * PDU has an invalid LUN.
814 */
815#define CMD_CXN_KILLED_ICD_INVALID 21 /* Command got invalidated
816 * internally due to the
817 * corresponding ICD not in a
818 * valid state
819 */
820#define CMD_CXN_KILLED_ITT_INVALID 22 /* Command got invalidated due
821 * to received PDU has an
822 * invalid ITT.
823 */
824#define CMD_CXN_KILLED_SEQ_OUTOFORDER 23 /* Command got invalidated due
825 * to received sequence buffer
826 * offset is out of order.
827 */
828#define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24 /* Command got invalidated
829 * internally due to a
830 * recieved PDU has an invalid
831 * DataSN
832 */
833#define CXN_INVALIDATE_NOTIFY 25 /* Connection invalidation
834 * completion notify.
835 */
836#define CXN_INVALIDATE_INDEX_NOTIFY 26 /* Connection invalidation
837 * completion
838 * with data PDU index.
839 */
840#define CMD_INVALIDATED_NOTIFY 27 /* Command invalidation
841 * completionnotifify.
842 */
843#define UNSOL_HDR_NOTIFY 28 /* Unsolicited header notify.*/
844#define UNSOL_DATA_NOTIFY 29 /* Unsolicited data notify.*/
845#define UNSOL_DATA_DIGEST_ERROR_NOTIFY 30 /* Unsolicited data digest
846 * error notify.
847 */
848#define DRIVERMSG_NOTIFY 31 /* TCP acknowledge based
849 * notification.
850 */
851#define CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN 32 /* Connection got invalidated
852 * internally due to command
853 * and data are not on same
854 * connection.
855 */
856#define SOL_CMD_KILLED_DIF_ERR 33 /* Solicited command got
857 * invalidated internally due
858 * to DIF error
859 */
860#define CXN_KILLED_SYN_RCVD 34 /* Connection got invalidated
861 * internally due to incoming
862 * TCP SYN
863 */
864#define CXN_KILLED_IMM_DATA_RCVD 35 /* Connection got invalidated
865 * internally due to an
866 * incoming Unsolicited PDU
867 * that has immediate data on
868 * the cxn
869 */
870
871void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
872 bool embedded, u8 sge_cnt);
873
874void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
875 u8 subsystem, u8 opcode, int cmd_len);
876
877#endif /* !BEISCSI_CMDS_H */
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
new file mode 100644
index 000000000000..b23526cb39d7
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -0,0 +1,646 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20
21#include <scsi/libiscsi.h>
22#include <scsi/scsi_transport_iscsi.h>
23#include <scsi/scsi_transport.h>
24#include <scsi/scsi_cmnd.h>
25#include <scsi/scsi_device.h>
26#include <scsi/scsi_host.h>
27#include <scsi/scsi.h>
28
29#include "be_iscsi.h"
30
31extern struct iscsi_transport beiscsi_iscsi_transport;
32
33/**
34 * beiscsi_session_create - creates a new iscsi session
35 * @cmds_max: max commands supported
36 * @qdepth: max queue depth supported
37 * @initial_cmdsn: initial iscsi CMDSN
38 */
39struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
40 u16 cmds_max,
41 u16 qdepth,
42 u32 initial_cmdsn)
43{
44 struct Scsi_Host *shost;
45 struct beiscsi_endpoint *beiscsi_ep;
46 struct iscsi_cls_session *cls_session;
47 struct iscsi_session *sess;
48 struct beiscsi_hba *phba;
49 struct iscsi_task *task;
50 struct beiscsi_io_task *io_task;
51 unsigned int max_size, num_cmd;
52 dma_addr_t bus_add;
53 u64 pa_addr;
54 void *vaddr;
55
56 SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n");
57
58 if (!ep) {
59 SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n");
60 return NULL;
61 }
62 beiscsi_ep = ep->dd_data;
63 phba = beiscsi_ep->phba;
64 shost = phba->shost;
65 if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
66 shost_printk(KERN_ERR, shost, "Cannot handle %d cmds."
67 "Max cmds per session supported is %d. Using %d. "
68 "\n", cmds_max,
69 beiscsi_ep->phba->params.wrbs_per_cxn,
70 beiscsi_ep->phba->params.wrbs_per_cxn);
71 cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
72 }
73
74 cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
75 shost, cmds_max,
76 sizeof(struct beiscsi_io_task),
77 initial_cmdsn, ISCSI_MAX_TARGET);
78 if (!cls_session)
79 return NULL;
80 sess = cls_session->dd_data;
81 max_size = ALIGN(sizeof(struct be_cmd_bhs), 64) * sess->cmds_max;
82 vaddr = pci_alloc_consistent(phba->pcidev, max_size, &bus_add);
83 pa_addr = (__u64) bus_add;
84
85 for (num_cmd = 0; num_cmd < sess->cmds_max; num_cmd++) {
86 task = sess->cmds[num_cmd];
87 io_task = task->dd_data;
88 io_task->cmd_bhs = vaddr;
89 io_task->bhs_pa.u.a64.address = pa_addr;
90 io_task->alloc_size = max_size;
91 vaddr += ALIGN(sizeof(struct be_cmd_bhs), 64);
92 pa_addr += ALIGN(sizeof(struct be_cmd_bhs), 64);
93 }
94 return cls_session;
95}
96
97/**
98 * beiscsi_session_destroy - destroys iscsi session
99 * @cls_session: pointer to iscsi cls session
100 *
101 * Destroys iSCSI session instance and releases
102 * resources allocated for it.
103 */
104void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
105{
106 struct iscsi_task *task;
107 struct beiscsi_io_task *io_task;
108 struct iscsi_session *sess = cls_session->dd_data;
109 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
110 struct beiscsi_hba *phba = iscsi_host_priv(shost);
111
112 task = sess->cmds[0];
113 io_task = task->dd_data;
114 pci_free_consistent(phba->pcidev,
115 io_task->alloc_size,
116 io_task->cmd_bhs,
117 io_task->bhs_pa.u.a64.address);
118 iscsi_session_teardown(cls_session);
119}
120
121/**
122 * beiscsi_conn_create - create an instance of iscsi connection
123 * @cls_session: ptr to iscsi_cls_session
124 * @cid: iscsi cid
125 */
126struct iscsi_cls_conn *
127beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
128{
129 struct beiscsi_hba *phba;
130 struct Scsi_Host *shost;
131 struct iscsi_cls_conn *cls_conn;
132 struct beiscsi_conn *beiscsi_conn;
133 struct iscsi_conn *conn;
134
135 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid"
136 "from iscsi layer=%d\n", cid);
137 shost = iscsi_session_to_shost(cls_session);
138 phba = iscsi_host_priv(shost);
139
140 cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
141 if (!cls_conn)
142 return NULL;
143
144 conn = cls_conn->dd_data;
145 beiscsi_conn = conn->dd_data;
146 beiscsi_conn->ep = NULL;
147 beiscsi_conn->phba = phba;
148 beiscsi_conn->conn = conn;
149 return cls_conn;
150}
151
152/**
153 * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table
154 * @beiscsi_conn: The pointer to beiscsi_conn structure
155 * @phba: The phba instance
156 * @cid: The cid to free
157 */
158static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
159 struct beiscsi_conn *beiscsi_conn,
160 unsigned int cid)
161{
162 if (phba->conn_table[cid]) {
163 SE_DEBUG(DBG_LVL_1,
164 "Connection table already occupied. Detected clash\n");
165 return -EINVAL;
166 } else {
167 SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n",
168 cid, beiscsi_conn);
169 phba->conn_table[cid] = beiscsi_conn;
170 }
171 return 0;
172}
173
174/**
175 * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
176 * @cls_session: pointer to iscsi cls session
177 * @cls_conn: pointer to iscsi cls conn
178 * @transport_fd: EP handle(64 bit)
179 *
180 * This function binds the TCP Conn with iSCSI Connection and Session.
181 */
182int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
183 struct iscsi_cls_conn *cls_conn,
184 u64 transport_fd, int is_leading)
185{
186 struct iscsi_conn *conn = cls_conn->dd_data;
187 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
188 struct Scsi_Host *shost =
189 (struct Scsi_Host *)iscsi_session_to_shost(cls_session);
190 struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
191 struct beiscsi_endpoint *beiscsi_ep;
192 struct iscsi_endpoint *ep;
193
194 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n");
195 ep = iscsi_lookup_endpoint(transport_fd);
196 if (!ep)
197 return -EINVAL;
198
199 beiscsi_ep = ep->dd_data;
200
201 if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
202 return -EINVAL;
203
204 if (beiscsi_ep->phba != phba) {
205 SE_DEBUG(DBG_LVL_8,
206 "beiscsi_ep->hba=%p not equal to phba=%p \n",
207 beiscsi_ep->phba, phba);
208 return -EEXIST;
209 }
210
211 beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
212 beiscsi_conn->ep = beiscsi_ep;
213 beiscsi_ep->conn = beiscsi_conn;
214 SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n",
215 beiscsi_conn, conn, beiscsi_ep->ep_cid);
216 return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
217}
218
219/**
220 * beiscsi_conn_get_param - get the iscsi parameter
221 * @cls_conn: pointer to iscsi cls conn
222 * @param: parameter type identifier
223 * @buf: buffer pointer
224 *
225 * returns iscsi parameter
226 */
227int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
228 enum iscsi_param param, char *buf)
229{
230 struct beiscsi_endpoint *beiscsi_ep;
231 struct iscsi_conn *conn = cls_conn->dd_data;
232 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
233 int len = 0;
234
235 beiscsi_ep = beiscsi_conn->ep;
236 if (!beiscsi_ep) {
237 SE_DEBUG(DBG_LVL_1,
238 "In beiscsi_conn_get_param , no beiscsi_ep\n");
239 return -1;
240 }
241
242 switch (param) {
243 case ISCSI_PARAM_CONN_PORT:
244 len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
245 break;
246 case ISCSI_PARAM_CONN_ADDRESS:
247 if (beiscsi_ep->ip_type == BE2_IPV4)
248 len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
249 else
250 len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
251 break;
252 default:
253 return iscsi_conn_get_param(cls_conn, param, buf);
254 }
255 return len;
256}
257
258int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
259 enum iscsi_param param, char *buf, int buflen)
260{
261 struct iscsi_conn *conn = cls_conn->dd_data;
262 struct iscsi_session *session = conn->session;
263 int ret;
264
265 ret = iscsi_set_param(cls_conn, param, buf, buflen);
266 if (ret)
267 return ret;
268 /*
269 * If userspace tried to set the value to higher than we can
270 * support override here.
271 */
272 switch (param) {
273 case ISCSI_PARAM_FIRST_BURST:
274 if (session->first_burst > 8192)
275 session->first_burst = 8192;
276 break;
277 case ISCSI_PARAM_MAX_RECV_DLENGTH:
278 if (conn->max_recv_dlength > 65536)
279 conn->max_recv_dlength = 65536;
280 break;
281 case ISCSI_PARAM_MAX_BURST:
282 if (session->first_burst > 262144)
283 session->first_burst = 262144;
284 break;
285 default:
286 return 0;
287 }
288
289 return 0;
290}
291
292/**
293 * beiscsi_get_host_param - get the iscsi parameter
294 * @shost: pointer to scsi_host structure
295 * @param: parameter type identifier
296 * @buf: buffer pointer
297 *
298 * returns host parameter
299 */
300int beiscsi_get_host_param(struct Scsi_Host *shost,
301 enum iscsi_host_param param, char *buf)
302{
303 struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
304 int len = 0;
305
306 switch (param) {
307 case ISCSI_HOST_PARAM_HWADDRESS:
308 be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address);
309 len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
310 break;
311 default:
312 return iscsi_host_get_param(shost, param, buf);
313 }
314 return len;
315}
316
317/**
318 * beiscsi_conn_get_stats - get the iscsi stats
319 * @cls_conn: pointer to iscsi cls conn
320 * @stats: pointer to iscsi_stats structure
321 *
322 * returns iscsi stats
323 */
324void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
325 struct iscsi_stats *stats)
326{
327 struct iscsi_conn *conn = cls_conn->dd_data;
328
329 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n");
330 stats->txdata_octets = conn->txdata_octets;
331 stats->rxdata_octets = conn->rxdata_octets;
332 stats->dataout_pdus = conn->dataout_pdus_cnt;
333 stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
334 stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
335 stats->datain_pdus = conn->datain_pdus_cnt;
336 stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
337 stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
338 stats->r2t_pdus = conn->r2t_pdus_cnt;
339 stats->digest_err = 0;
340 stats->timeout_err = 0;
341 stats->custom_length = 0;
342 strcpy(stats->custom[0].desc, "eh_abort_cnt");
343 stats->custom[0].value = conn->eh_abort_cnt;
344}
345
346/**
347 * beiscsi_set_params_for_offld - get the parameters for offload
348 * @beiscsi_conn: pointer to beiscsi_conn
349 * @params: pointer to offload_params structure
350 */
351static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
352 struct beiscsi_offload_params *params)
353{
354 struct iscsi_conn *conn = beiscsi_conn->conn;
355 struct iscsi_session *session = conn->session;
356
357 AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
358 params, session->max_burst);
359 AMAP_SET_BITS(struct amap_beiscsi_offload_params,
360 max_send_data_segment_length, params,
361 conn->max_xmit_dlength);
362 AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
363 params, session->first_burst);
364 AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
365 session->erl);
366 AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
367 conn->datadgst_en);
368 AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
369 conn->hdrdgst_en);
370 AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
371 session->initial_r2t_en);
372 AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
373 session->imm_data_en);
374 AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
375 (conn->exp_statsn - 1));
376}
377
378/**
379 * beiscsi_conn_start - offload of session to chip
380 * @cls_conn: pointer to beiscsi_conn
381 */
382int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
383{
384 struct iscsi_conn *conn = cls_conn->dd_data;
385 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
386 struct beiscsi_endpoint *beiscsi_ep;
387 struct beiscsi_offload_params params;
388 struct iscsi_session *session = conn->session;
389 struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
390 struct beiscsi_hba *phba = iscsi_host_priv(shost);
391
392 memset(&params, 0, sizeof(struct beiscsi_offload_params));
393 beiscsi_ep = beiscsi_conn->ep;
394 if (!beiscsi_ep)
395 SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
396
397 free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
398 beiscsi_conn->login_in_progress = 0;
399 beiscsi_set_params_for_offld(beiscsi_conn, &params);
400 beiscsi_offload_connection(beiscsi_conn, &params);
401 iscsi_conn_start(cls_conn);
402 return 0;
403}
404
405/**
406 * beiscsi_get_cid - Allocate a cid
407 * @phba: The phba instance
408 */
409static int beiscsi_get_cid(struct beiscsi_hba *phba)
410{
411 unsigned short cid = 0xFFFF;
412
413 if (!phba->avlbl_cids)
414 return cid;
415
416 cid = phba->cid_array[phba->cid_alloc++];
417 if (phba->cid_alloc == phba->params.cxns_per_ctrl)
418 phba->cid_alloc = 0;
419 phba->avlbl_cids--;
420 return cid;
421}
422
423/**
424 * beiscsi_open_conn - Ask FW to open a TCP connection
425 * @ep: endpoint to be used
426 * @src_addr: The source IP address
427 * @dst_addr: The Destination IP address
428 *
429 * Asks the FW to open a TCP connection
430 */
431static int beiscsi_open_conn(struct iscsi_endpoint *ep,
432 struct sockaddr *src_addr,
433 struct sockaddr *dst_addr, int non_blocking)
434{
435 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
436 struct beiscsi_hba *phba = beiscsi_ep->phba;
437 int ret = -1;
438
439 beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
440 if (beiscsi_ep->ep_cid == 0xFFFF) {
441 SE_DEBUG(DBG_LVL_1, "No free cid available\n");
442 return ret;
443 }
444 SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ",
445 beiscsi_ep->ep_cid);
446 phba->ep_array[beiscsi_ep->ep_cid] = ep;
447 if (beiscsi_ep->ep_cid >
448 (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) {
449 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
450 return ret;
451 }
452
453 beiscsi_ep->cid_vld = 0;
454 return mgmt_open_connection(phba, dst_addr, beiscsi_ep);
455}
456
457/**
458 * beiscsi_put_cid - Free the cid
459 * @phba: The phba for which the cid is being freed
460 * @cid: The cid to free
461 */
462static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
463{
464 phba->avlbl_cids++;
465 phba->cid_array[phba->cid_free++] = cid;
466 if (phba->cid_free == phba->params.cxns_per_ctrl)
467 phba->cid_free = 0;
468}
469
470/**
471 * beiscsi_free_ep - free endpoint
472 * @ep: pointer to iscsi endpoint structure
473 */
474static void beiscsi_free_ep(struct iscsi_endpoint *ep)
475{
476 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
477 struct beiscsi_hba *phba = beiscsi_ep->phba;
478
479 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
480 beiscsi_ep->phba = NULL;
481 iscsi_destroy_endpoint(ep);
482}
483
484/**
485 * beiscsi_ep_connect - Ask chip to create TCP Conn
486 * @scsi_host: Pointer to scsi_host structure
487 * @dst_addr: The IP address of Target
488 * @non_blocking: blocking or non-blocking call
489 *
490 * This routines first asks chip to create a connection and then allocates an EP
491 */
492struct iscsi_endpoint *
493beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
494 int non_blocking)
495{
496 struct beiscsi_hba *phba;
497 struct beiscsi_endpoint *beiscsi_ep;
498 struct iscsi_endpoint *ep;
499 int ret;
500
501 SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n");
502 if (shost)
503 phba = iscsi_host_priv(shost);
504 else {
505 ret = -ENXIO;
506 SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
507 return ERR_PTR(ret);
508 }
509 ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
510 if (!ep) {
511 ret = -ENOMEM;
512 return ERR_PTR(ret);
513 }
514
515 beiscsi_ep = ep->dd_data;
516 beiscsi_ep->phba = phba;
517
518 if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
519 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
520 ret = -ENOMEM;
521 goto free_ep;
522 }
523
524 return ep;
525
526free_ep:
527 beiscsi_free_ep(ep);
528 return ERR_PTR(ret);
529}
530
531/**
532 * beiscsi_ep_poll - Poll to see if connection is established
533 * @ep: endpoint to be used
534 * @timeout_ms: timeout specified in millisecs
535 *
536 * Poll to see if TCP connection established
537 */
538int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
539{
540 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
541
542 SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_poll\n");
543 if (beiscsi_ep->cid_vld == 1)
544 return 1;
545 else
546 return 0;
547}
548
549/**
550 * beiscsi_close_conn - Upload the connection
551 * @ep: The iscsi endpoint
552 * @flag: The type of connection closure
553 */
554static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag)
555{
556 int ret = 0;
557 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
558 struct beiscsi_hba *phba = beiscsi_ep->phba;
559
560 if (MGMT_STATUS_SUCCESS !=
561 mgmt_upload_connection(phba, beiscsi_ep->ep_cid,
562 CONNECTION_UPLOAD_GRACEFUL)) {
563 SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
564 beiscsi_ep->ep_cid);
565 ret = -1;
566 }
567
568 return ret;
569}
570
571/**
572 * beiscsi_ep_disconnect - Tears down the TCP connection
573 * @ep: endpoint to be used
574 *
575 * Tears down the TCP connection
576 */
577void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
578{
579 struct beiscsi_conn *beiscsi_conn;
580 struct beiscsi_endpoint *beiscsi_ep;
581 struct beiscsi_hba *phba;
582 int flag = 0;
583
584 beiscsi_ep = ep->dd_data;
585 phba = beiscsi_ep->phba;
586 SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n");
587
588 if (beiscsi_ep->conn) {
589 beiscsi_conn = beiscsi_ep->conn;
590 iscsi_suspend_queue(beiscsi_conn->conn);
591 beiscsi_close_conn(ep, flag);
592 }
593
594 beiscsi_free_ep(ep);
595}
596
597/**
598 * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
599 * @phba: The phba instance
600 * @cid: The cid to free
601 */
602static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
603 unsigned int cid)
604{
605 if (phba->conn_table[cid])
606 phba->conn_table[cid] = NULL;
607 else {
608 SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n");
609 return -EINVAL;
610 }
611 return 0;
612}
613
614/**
615 * beiscsi_conn_stop - Invalidate and stop the connection
616 * @cls_conn: pointer to get iscsi_conn
617 * @flag: The type of connection closure
618 */
619void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
620{
621 struct iscsi_conn *conn = cls_conn->dd_data;
622 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
623 struct beiscsi_endpoint *beiscsi_ep;
624 struct iscsi_session *session = conn->session;
625 struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
626 struct beiscsi_hba *phba = iscsi_host_priv(shost);
627 unsigned int status;
628 unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
629
630 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
631 beiscsi_ep = beiscsi_conn->ep;
632 if (!beiscsi_ep) {
633 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
634 return;
635 }
636 status = mgmt_invalidate_connection(phba, beiscsi_ep,
637 beiscsi_ep->ep_cid, 1,
638 savecfg_flag);
639 if (status != MGMT_STATUS_SUCCESS) {
640 SE_DEBUG(DBG_LVL_1,
641 "mgmt_invalidate_connection Failed for cid=%d \n",
642 beiscsi_ep->ep_cid);
643 }
644 beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
645 iscsi_conn_stop(cls_conn, flag);
646}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
new file mode 100644
index 000000000000..f92ffc5349fb
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -0,0 +1,75 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20
21#ifndef _BE_ISCSI_
22#define _BE_ISCSI_
23
24#include "be_main.h"
25#include "be_mgmt.h"
26
27#define BE2_IPV4 0x1
28#define BE2_IPV6 0x10
29
30void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
31 struct beiscsi_offload_params *params);
32
33void beiscsi_offload_iscsi(struct beiscsi_hba *phba, struct iscsi_conn *conn,
34 struct beiscsi_conn *beiscsi_conn,
35 unsigned int fw_handle);
36
37struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
38 uint16_t cmds_max,
39 uint16_t qdepth,
40 uint32_t initial_cmdsn);
41
42void beiscsi_session_destroy(struct iscsi_cls_session *cls_session);
43
44struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session
45 *cls_session, uint32_t cid);
46
47int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
48 struct iscsi_cls_conn *cls_conn,
49 uint64_t transport_fd, int is_leading);
50
51int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
52 enum iscsi_param param, char *buf);
53
54int beiscsi_get_host_param(struct Scsi_Host *shost,
55 enum iscsi_host_param param, char *buf);
56
57int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
58 enum iscsi_param param, char *buf, int buflen);
59
60int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn);
61
62void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag);
63
64struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost,
65 struct sockaddr *dst_addr,
66 int non_blocking);
67
68int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);
69
70void beiscsi_ep_disconnect(struct iscsi_endpoint *ep);
71
72void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
73 struct iscsi_stats *stats);
74
75#endif
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
new file mode 100644
index 000000000000..d520fe875859
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -0,0 +1,3393 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20#include <linux/reboot.h>
21#include <linux/delay.h>
22#include <linux/interrupt.h>
23#include <linux/blkdev.h>
24#include <linux/pci.h>
25#include <linux/string.h>
26#include <linux/kernel.h>
27#include <linux/semaphore.h>
28
29#include <scsi/libiscsi.h>
30#include <scsi/scsi_transport_iscsi.h>
31#include <scsi/scsi_transport.h>
32#include <scsi/scsi_cmnd.h>
33#include <scsi/scsi_device.h>
34#include <scsi/scsi_host.h>
35#include <scsi/scsi.h>
36#include "be_main.h"
37#include "be_iscsi.h"
38#include "be_mgmt.h"
39
40static unsigned int be_iopoll_budget = 10;
41static unsigned int be_max_phys_size = 64;
42static unsigned int enable_msix;
43
44MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
45MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
46MODULE_AUTHOR("ServerEngines Corporation");
47MODULE_LICENSE("GPL");
48module_param(be_iopoll_budget, int, 0);
49module_param(enable_msix, int, 0);
50module_param(be_max_phys_size, uint, S_IRUGO);
51MODULE_PARM_DESC(be_max_phys_size, "Maximum Size (In Kilobytes) of physically"
52 "contiguous memory that can be allocated."
53 "Range is 16 - 128");
54
55static int beiscsi_slave_configure(struct scsi_device *sdev)
56{
57 blk_queue_max_segment_size(sdev->request_queue, 65536);
58 return 0;
59}
60
61static struct scsi_host_template beiscsi_sht = {
62 .module = THIS_MODULE,
63 .name = "ServerEngines 10Gbe open-iscsi Initiator Driver",
64 .proc_name = DRV_NAME,
65 .queuecommand = iscsi_queuecommand,
66 .eh_abort_handler = iscsi_eh_abort,
67 .change_queue_depth = iscsi_change_queue_depth,
68 .slave_configure = beiscsi_slave_configure,
69 .target_alloc = iscsi_target_alloc,
70 .eh_device_reset_handler = iscsi_eh_device_reset,
71 .eh_target_reset_handler = iscsi_eh_target_reset,
72 .sg_tablesize = BEISCSI_SGLIST_ELEMENTS,
73 .can_queue = BE2_IO_DEPTH,
74 .this_id = -1,
75 .max_sectors = BEISCSI_MAX_SECTORS,
76 .cmd_per_lun = BEISCSI_CMD_PER_LUN,
77 .use_clustering = ENABLE_CLUSTERING,
78};
79static struct scsi_transport_template *beiscsi_scsi_transport;
80
81/*------------------- PCI Driver operations and data ----------------- */
82static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
83 { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
84 { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
85 { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
86 { 0 }
87};
88MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
89
90static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
91{
92 struct beiscsi_hba *phba;
93 struct Scsi_Host *shost;
94
95 shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0);
96 if (!shost) {
97 dev_err(&pcidev->dev, "beiscsi_hba_alloc -"
98 "iscsi_host_alloc failed \n");
99 return NULL;
100 }
101 shost->dma_boundary = pcidev->dma_mask;
102 shost->max_id = BE2_MAX_SESSIONS;
103 shost->max_channel = 0;
104 shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
105 shost->max_lun = BEISCSI_NUM_MAX_LUN;
106 shost->transportt = beiscsi_scsi_transport;
107
108 phba = iscsi_host_priv(shost);
109 memset(phba, 0, sizeof(*phba));
110 phba->shost = shost;
111 phba->pcidev = pci_dev_get(pcidev);
112
113 if (iscsi_host_add(shost, &phba->pcidev->dev))
114 goto free_devices;
115 return phba;
116
117free_devices:
118 pci_dev_put(phba->pcidev);
119 iscsi_host_free(phba->shost);
120 return NULL;
121}
122
123static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba)
124{
125 if (phba->csr_va) {
126 iounmap(phba->csr_va);
127 phba->csr_va = NULL;
128 }
129 if (phba->db_va) {
130 iounmap(phba->db_va);
131 phba->db_va = NULL;
132 }
133 if (phba->pci_va) {
134 iounmap(phba->pci_va);
135 phba->pci_va = NULL;
136 }
137}
138
139static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
140 struct pci_dev *pcidev)
141{
142 u8 __iomem *addr;
143
144 addr = ioremap_nocache(pci_resource_start(pcidev, 2),
145 pci_resource_len(pcidev, 2));
146 if (addr == NULL)
147 return -ENOMEM;
148 phba->ctrl.csr = addr;
149 phba->csr_va = addr;
150 phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2);
151
152 addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024);
153 if (addr == NULL)
154 goto pci_map_err;
155 phba->ctrl.db = addr;
156 phba->db_va = addr;
157 phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4);
158
159 addr = ioremap_nocache(pci_resource_start(pcidev, 1),
160 pci_resource_len(pcidev, 1));
161 if (addr == NULL)
162 goto pci_map_err;
163 phba->ctrl.pcicfg = addr;
164 phba->pci_va = addr;
165 phba->pci_pa.u.a64.address = pci_resource_start(pcidev, 1);
166 return 0;
167
168pci_map_err:
169 beiscsi_unmap_pci_function(phba);
170 return -ENOMEM;
171}
172
173static int beiscsi_enable_pci(struct pci_dev *pcidev)
174{
175 int ret;
176
177 ret = pci_enable_device(pcidev);
178 if (ret) {
179 dev_err(&pcidev->dev, "beiscsi_enable_pci - enable device "
180 "failed. Returning -ENODEV\n");
181 return ret;
182 }
183
184 if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
185 ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
186 if (ret) {
187 dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");
188 pci_disable_device(pcidev);
189 return ret;
190 }
191 }
192 return 0;
193}
194
195static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
196{
197 struct be_ctrl_info *ctrl = &phba->ctrl;
198 struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced;
199 struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem;
200 int status = 0;
201
202 ctrl->pdev = pdev;
203 status = beiscsi_map_pci_bars(phba, pdev);
204 if (status)
205 return status;
206
207 mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
208 mbox_mem_alloc->va = pci_alloc_consistent(pdev,
209 mbox_mem_alloc->size,
210 &mbox_mem_alloc->dma);
211 if (!mbox_mem_alloc->va) {
212 beiscsi_unmap_pci_function(phba);
213 status = -ENOMEM;
214 return status;
215 }
216
217 mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
218 mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
219 mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
220 memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
221 spin_lock_init(&ctrl->mbox_lock);
222 return status;
223}
224
225static void beiscsi_get_params(struct beiscsi_hba *phba)
226{
227 phba->params.ios_per_ctrl = BE2_IO_DEPTH;
228 phba->params.cxns_per_ctrl = BE2_MAX_SESSIONS;
229 phba->params.asyncpdus_per_ctrl = BE2_ASYNCPDUS;
230 phba->params.icds_per_ctrl = BE2_MAX_ICDS / 2;
231 phba->params.num_sge_per_io = BE2_SGE;
232 phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
233 phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
234 phba->params.eq_timer = 64;
235 phba->params.num_eq_entries =
236 (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
237 512) + 1) * 512;
238 phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024)
239 ? 1024 : phba->params.num_eq_entries;
240 SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n",
241 phba->params.num_eq_entries);
242 phba->params.num_cq_entries =
243 (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) /
244 512) + 1) * 512;
245 SE_DEBUG(DBG_LVL_8,
246 "phba->params.num_cq_entries=%d BE2_CMDS_PER_CXN=%d"
247 "BE2_LOGOUTS=%d BE2_TMFS=%d BE2_ASYNCPDUS=%d \n",
248 phba->params.num_cq_entries, BE2_CMDS_PER_CXN,
249 BE2_LOGOUTS, BE2_TMFS, BE2_ASYNCPDUS);
250 phba->params.wrbs_per_cxn = 256;
251}
252
253static void hwi_ring_eq_db(struct beiscsi_hba *phba,
254 unsigned int id, unsigned int clr_interrupt,
255 unsigned int num_processed,
256 unsigned char rearm, unsigned char event)
257{
258 u32 val = 0;
259 val |= id & DB_EQ_RING_ID_MASK;
260 if (rearm)
261 val |= 1 << DB_EQ_REARM_SHIFT;
262 if (clr_interrupt)
263 val |= 1 << DB_EQ_CLR_SHIFT;
264 if (event)
265 val |= 1 << DB_EQ_EVNT_SHIFT;
266 val |= num_processed << DB_EQ_NUM_POPPED_SHIFT;
267 iowrite32(val, phba->db_va + DB_EQ_OFFSET);
268}
269
270/**
271 * be_isr - The isr routine of the driver.
272 * @irq: Not used
273 * @dev_id: Pointer to host adapter structure
274 */
275static irqreturn_t be_isr(int irq, void *dev_id)
276{
277 struct beiscsi_hba *phba;
278 struct hwi_controller *phwi_ctrlr;
279 struct hwi_context_memory *phwi_context;
280 struct be_eq_entry *eqe = NULL;
281 struct be_queue_info *eq;
282 struct be_queue_info *cq;
283 unsigned long flags, index;
284 unsigned int num_eq_processed;
285 struct be_ctrl_info *ctrl;
286 int isr;
287
288 phba = dev_id;
289 if (!enable_msix) {
290 ctrl = &phba->ctrl;;
291 isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
292 (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
293 if (!isr)
294 return IRQ_NONE;
295 }
296
297 phwi_ctrlr = phba->phwi_ctrlr;
298 phwi_context = phwi_ctrlr->phwi_ctxt;
299 eq = &phwi_context->be_eq.q;
300 cq = &phwi_context->be_cq;
301 index = 0;
302 eqe = queue_tail_node(eq);
303 if (!eqe)
304 SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");
305
306 num_eq_processed = 0;
307 if (blk_iopoll_enabled) {
308 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
309 & EQE_VALID_MASK) {
310 if (!blk_iopoll_sched_prep(&phba->iopoll))
311 blk_iopoll_sched(&phba->iopoll);
312
313 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
314 queue_tail_inc(eq);
315 eqe = queue_tail_node(eq);
316 num_eq_processed++;
317 SE_DEBUG(DBG_LVL_8, "Valid EQE\n");
318 }
319 if (num_eq_processed) {
320 hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 0, 1);
321 return IRQ_HANDLED;
322 } else
323 return IRQ_NONE;
324 } else {
325 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
326 & EQE_VALID_MASK) {
327
328 if (((eqe->dw[offsetof(struct amap_eq_entry,
329 resource_id) / 32] &
330 EQE_RESID_MASK) >> 16) != cq->id) {
331 spin_lock_irqsave(&phba->isr_lock, flags);
332 phba->todo_mcc_cq = 1;
333 spin_unlock_irqrestore(&phba->isr_lock, flags);
334 } else {
335 spin_lock_irqsave(&phba->isr_lock, flags);
336 phba->todo_cq = 1;
337 spin_unlock_irqrestore(&phba->isr_lock, flags);
338 }
339 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
340 queue_tail_inc(eq);
341 eqe = queue_tail_node(eq);
342 num_eq_processed++;
343 }
344 if (phba->todo_cq || phba->todo_mcc_cq)
345 queue_work(phba->wq, &phba->work_cqs);
346
347 if (num_eq_processed) {
348 hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 1, 1);
349 return IRQ_HANDLED;
350 } else
351 return IRQ_NONE;
352 }
353}
354
355static int beiscsi_init_irqs(struct beiscsi_hba *phba)
356{
357 struct pci_dev *pcidev = phba->pcidev;
358 int ret;
359
360 ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba);
361 if (ret) {
362 shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
363 "Failed to register irq\\n");
364 return ret;
365 }
366 return 0;
367}
368
369static void hwi_ring_cq_db(struct beiscsi_hba *phba,
370 unsigned int id, unsigned int num_processed,
371 unsigned char rearm, unsigned char event)
372{
373 u32 val = 0;
374 val |= id & DB_CQ_RING_ID_MASK;
375 if (rearm)
376 val |= 1 << DB_CQ_REARM_SHIFT;
377 val |= num_processed << DB_CQ_NUM_POPPED_SHIFT;
378 iowrite32(val, phba->db_va + DB_CQ_OFFSET);
379}
380
381/*
382 * async pdus include
383 * a. unsolicited NOP-In (target initiated NOP-In)
384 * b. Async Messages
385 * c. Reject PDU
386 * d. Login response
387 * These headers arrive unprocessed by the EP firmware and iSCSI layer
388 * process them
389 */
390static unsigned int
391beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
392 struct beiscsi_hba *phba,
393 unsigned short cid,
394 struct pdu_base *ppdu,
395 unsigned long pdu_len,
396 void *pbuffer, unsigned long buf_len)
397{
398 struct iscsi_conn *conn = beiscsi_conn->conn;
399 struct iscsi_session *session = conn->session;
400
401 switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] &
402 PDUBASE_OPCODE_MASK) {
403 case ISCSI_OP_NOOP_IN:
404 pbuffer = NULL;
405 buf_len = 0;
406 break;
407 case ISCSI_OP_ASYNC_EVENT:
408 break;
409 case ISCSI_OP_REJECT:
410 WARN_ON(!pbuffer);
411 WARN_ON(!(buf_len == 48));
412 SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n");
413 break;
414 case ISCSI_OP_LOGIN_RSP:
415 break;
416 default:
417 shost_printk(KERN_WARNING, phba->shost,
418 "Unrecognized opcode 0x%x in async msg \n",
419 (ppdu->
420 dw[offsetof(struct amap_pdu_base, opcode) / 32]
421 & PDUBASE_OPCODE_MASK));
422 return 1;
423 }
424
425 spin_lock_bh(&session->lock);
426 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len);
427 spin_unlock_bh(&session->lock);
428 return 0;
429}
430
431static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
432{
433 struct sgl_handle *psgl_handle;
434
435 if (phba->io_sgl_hndl_avbl) {
436 SE_DEBUG(DBG_LVL_8,
437 "In alloc_io_sgl_handle,io_sgl_alloc_index=%d \n",
438 phba->io_sgl_alloc_index);
439 psgl_handle = phba->io_sgl_hndl_base[phba->
440 io_sgl_alloc_index];
441 phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL;
442 phba->io_sgl_hndl_avbl--;
443 if (phba->io_sgl_alloc_index == (phba->params.ios_per_ctrl - 1))
444 phba->io_sgl_alloc_index = 0;
445 else
446 phba->io_sgl_alloc_index++;
447 } else
448 psgl_handle = NULL;
449 return psgl_handle;
450}
451
452static void
453free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
454{
455 SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d \n",
456 phba->io_sgl_free_index);
457 if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) {
458 /*
459 * this can happen if clean_task is called on a task that
460 * failed in xmit_task or alloc_pdu.
461 */
462 SE_DEBUG(DBG_LVL_8,
463 "Double Free in IO SGL io_sgl_free_index=%d,"
464 "value there=%p \n", phba->io_sgl_free_index,
465 phba->io_sgl_hndl_base[phba->io_sgl_free_index]);
466 return;
467 }
468 phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
469 phba->io_sgl_hndl_avbl++;
470 if (phba->io_sgl_free_index == (phba->params.ios_per_ctrl - 1))
471 phba->io_sgl_free_index = 0;
472 else
473 phba->io_sgl_free_index++;
474}
475
476/**
477 * alloc_wrb_handle - To allocate a wrb handle
478 * @phba: The hba pointer
479 * @cid: The cid to use for allocation
480 * @index: index allocation and wrb index
481 *
482 * This happens under session_lock until submission to chip
483 */
484struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
485 int index)
486{
487 struct hwi_wrb_context *pwrb_context;
488 struct hwi_controller *phwi_ctrlr;
489 struct wrb_handle *pwrb_handle;
490
491 phwi_ctrlr = phba->phwi_ctrlr;
492 pwrb_context = &phwi_ctrlr->wrb_context[cid];
493 pwrb_handle = pwrb_context->pwrb_handle_base[index];
494 pwrb_handle->wrb_index = index;
495 pwrb_handle->nxt_wrb_index = index;
496 return pwrb_handle;
497}
498
499/**
500 * free_wrb_handle - To free the wrb handle back to pool
501 * @phba: The hba pointer
502 * @pwrb_context: The context to free from
503 * @pwrb_handle: The wrb_handle to free
504 *
505 * This happens under session_lock until submission to chip
506 */
507static void
508free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
509 struct wrb_handle *pwrb_handle)
510{
511 SE_DEBUG(DBG_LVL_8,
512 "FREE WRB: pwrb_handle=%p free_index=%d=0x%x"
513 "wrb_handles_available=%d \n",
514 pwrb_handle, pwrb_context->free_index,
515 pwrb_context->free_index, pwrb_context->wrb_handles_available);
516}
517
518static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
519{
520 struct sgl_handle *psgl_handle;
521
522 if (phba->eh_sgl_hndl_avbl) {
523 psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
524 phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
525 SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x \n",
526 phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index);
527 phba->eh_sgl_hndl_avbl--;
528 if (phba->eh_sgl_alloc_index ==
529 (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl -
530 1))
531 phba->eh_sgl_alloc_index = 0;
532 else
533 phba->eh_sgl_alloc_index++;
534 } else
535 psgl_handle = NULL;
536 return psgl_handle;
537}
538
539void
540free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
541{
542
543 if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) {
544 /*
545 * this can happen if clean_task is called on a task that
546 * failed in xmit_task or alloc_pdu.
547 */
548 SE_DEBUG(DBG_LVL_8,
549 "Double Free in eh SGL ,eh_sgl_free_index=%d \n",
550 phba->eh_sgl_free_index);
551 return;
552 }
553 phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle;
554 phba->eh_sgl_hndl_avbl++;
555 if (phba->eh_sgl_free_index ==
556 (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 1))
557 phba->eh_sgl_free_index = 0;
558 else
559 phba->eh_sgl_free_index++;
560}
561
562static void
563be_complete_io(struct beiscsi_conn *beiscsi_conn,
564 struct iscsi_task *task, struct sol_cqe *psol)
565{
566 struct beiscsi_io_task *io_task = task->dd_data;
567 struct be_status_bhs *sts_bhs =
568 (struct be_status_bhs *)io_task->cmd_bhs;
569 struct iscsi_conn *conn = beiscsi_conn->conn;
570 unsigned int sense_len;
571 unsigned char *sense;
572 u32 resid = 0, exp_cmdsn, max_cmdsn;
573 u8 rsp, status, flags;
574
575 exp_cmdsn = be32_to_cpu(psol->
576 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
577 & SOL_EXP_CMD_SN_MASK);
578 max_cmdsn = be32_to_cpu((psol->
579 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
580 & SOL_EXP_CMD_SN_MASK) +
581 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
582 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
583 rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
584 & SOL_RESP_MASK) >> 16);
585 status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
586 & SOL_STS_MASK) >> 8);
587 flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
588 & SOL_FLAGS_MASK) >> 24) | 0x80;
589
590 task->sc->result = (DID_OK << 16) | status;
591 if (rsp != ISCSI_STATUS_CMD_COMPLETED) {
592 task->sc->result = DID_ERROR << 16;
593 goto unmap;
594 }
595
596 /* bidi not initially supported */
597 if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
598 resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
599 32] & SOL_RES_CNT_MASK);
600
601 if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
602 task->sc->result = DID_ERROR << 16;
603
604 if (flags & ISCSI_FLAG_CMD_UNDERFLOW) {
605 scsi_set_resid(task->sc, resid);
606 if (!status && (scsi_bufflen(task->sc) - resid <
607 task->sc->underflow))
608 task->sc->result = DID_ERROR << 16;
609 }
610 }
611
612 if (status == SAM_STAT_CHECK_CONDITION) {
613 sense = sts_bhs->sense_info + sizeof(unsigned short);
614 sense_len =
615 cpu_to_be16((unsigned short)(sts_bhs->sense_info[0]));
616 memcpy(task->sc->sense_buffer, sense,
617 min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
618 }
619 if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
620 if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
621 & SOL_RES_CNT_MASK)
622 conn->rxdata_octets += (psol->
623 dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
624 & SOL_RES_CNT_MASK);
625 }
626unmap:
627 scsi_dma_unmap(io_task->scsi_cmnd);
628 iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
629}
630
631static void
632be_complete_logout(struct beiscsi_conn *beiscsi_conn,
633 struct iscsi_task *task, struct sol_cqe *psol)
634{
635 struct iscsi_logout_rsp *hdr;
636 struct iscsi_conn *conn = beiscsi_conn->conn;
637
638 hdr = (struct iscsi_logout_rsp *)task->hdr;
639 hdr->t2wait = 5;
640 hdr->t2retain = 0;
641 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
642 & SOL_FLAGS_MASK) >> 24) | 0x80;
643 hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
644 32] & SOL_RESP_MASK);
645 hdr->exp_cmdsn = cpu_to_be32(psol->
646 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
647 & SOL_EXP_CMD_SN_MASK);
648 hdr->max_cmdsn = be32_to_cpu((psol->
649 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
650 & SOL_EXP_CMD_SN_MASK) +
651 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
652 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
653 hdr->hlength = 0;
654
655 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
656}
657
658static void
659be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
660 struct iscsi_task *task, struct sol_cqe *psol)
661{
662 struct iscsi_tm_rsp *hdr;
663 struct iscsi_conn *conn = beiscsi_conn->conn;
664
665 hdr = (struct iscsi_tm_rsp *)task->hdr;
666 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
667 & SOL_FLAGS_MASK) >> 24) | 0x80;
668 hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
669 32] & SOL_RESP_MASK);
670 hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
671 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
672 hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
673 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
674 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
675 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
676 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
677}
678
679static void
680hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
681 struct beiscsi_hba *phba, struct sol_cqe *psol)
682{
683 struct hwi_wrb_context *pwrb_context;
684 struct wrb_handle *pwrb_handle;
685 struct hwi_controller *phwi_ctrlr;
686 struct iscsi_conn *conn = beiscsi_conn->conn;
687 struct iscsi_session *session = conn->session;
688
689 phwi_ctrlr = phba->phwi_ctrlr;
690 pwrb_context = &phwi_ctrlr->wrb_context[((psol->
691 dw[offsetof(struct amap_sol_cqe, cid) / 32] &
692 SOL_CID_MASK) >> 6)];
693 pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
694 dw[offsetof(struct amap_sol_cqe, wrb_index) /
695 32] & SOL_WRB_INDEX_MASK) >> 16)];
696 spin_lock_bh(&session->lock);
697 free_wrb_handle(phba, pwrb_context, pwrb_handle);
698 spin_unlock_bh(&session->lock);
699}
700
701static void
702be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
703 struct iscsi_task *task, struct sol_cqe *psol)
704{
705 struct iscsi_nopin *hdr;
706 struct iscsi_conn *conn = beiscsi_conn->conn;
707
708 hdr = (struct iscsi_nopin *)task->hdr;
709 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
710 & SOL_FLAGS_MASK) >> 24) | 0x80;
711 hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
712 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
713 hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
714 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
715 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
716 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
717 hdr->opcode = ISCSI_OP_NOOP_IN;
718 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
719}
720
721static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
722 struct beiscsi_hba *phba, struct sol_cqe *psol)
723{
724 struct hwi_wrb_context *pwrb_context;
725 struct wrb_handle *pwrb_handle;
726 struct iscsi_wrb *pwrb = NULL;
727 struct hwi_controller *phwi_ctrlr;
728 struct iscsi_task *task;
729 struct beiscsi_io_task *io_task;
730 struct iscsi_conn *conn = beiscsi_conn->conn;
731 struct iscsi_session *session = conn->session;
732
733 phwi_ctrlr = phba->phwi_ctrlr;
734
735 pwrb_context = &phwi_ctrlr->
736 wrb_context[((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32]
737 & SOL_CID_MASK) >> 6)];
738 pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
739 dw[offsetof(struct amap_sol_cqe, wrb_index) /
740 32] & SOL_WRB_INDEX_MASK) >> 16)];
741
742 task = pwrb_handle->pio_handle;
743 io_task = task->dd_data;
744 spin_lock_bh(&session->lock);
745 pwrb = pwrb_handle->pwrb;
746 switch ((pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
747 WRB_TYPE_MASK) >> 28) {
748 case HWH_TYPE_IO:
749 case HWH_TYPE_IO_RD:
750 if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
751 ISCSI_OP_NOOP_OUT) {
752 be_complete_nopin_resp(beiscsi_conn, task, psol);
753 } else
754 be_complete_io(beiscsi_conn, task, psol);
755 break;
756
757 case HWH_TYPE_LOGOUT:
758 be_complete_logout(beiscsi_conn, task, psol);
759 break;
760
761 case HWH_TYPE_LOGIN:
762 SE_DEBUG(DBG_LVL_1,
763 "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd"
764 "- Solicited path \n");
765 break;
766
767 case HWH_TYPE_TMF:
768 be_complete_tmf(beiscsi_conn, task, psol);
769 break;
770
771 case HWH_TYPE_NOP:
772 be_complete_nopin_resp(beiscsi_conn, task, psol);
773 break;
774
775 default:
776 shost_printk(KERN_WARNING, phba->shost,
777 "wrb_index 0x%x CID 0x%x\n",
778 ((psol->dw[offsetof(struct amap_iscsi_wrb, type) /
779 32] & SOL_WRB_INDEX_MASK) >> 16),
780 ((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32]
781 & SOL_CID_MASK) >> 6));
782 break;
783 }
784
785 spin_unlock_bh(&session->lock);
786}
787
788static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context
789 *pasync_ctx, unsigned int is_header,
790 unsigned int host_write_ptr)
791{
792 if (is_header)
793 return &pasync_ctx->async_entry[host_write_ptr].
794 header_busy_list;
795 else
796 return &pasync_ctx->async_entry[host_write_ptr].data_busy_list;
797}
798
799static struct async_pdu_handle *
800hwi_get_async_handle(struct beiscsi_hba *phba,
801 struct beiscsi_conn *beiscsi_conn,
802 struct hwi_async_pdu_context *pasync_ctx,
803 struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index)
804{
805 struct be_bus_address phys_addr;
806 struct list_head *pbusy_list;
807 struct async_pdu_handle *pasync_handle = NULL;
808 int buffer_len = 0;
809 unsigned char buffer_index = -1;
810 unsigned char is_header = 0;
811
812 phys_addr.u.a32.address_lo =
813 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
814 ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
815 & PDUCQE_DPL_MASK) >> 16);
816 phys_addr.u.a32.address_hi =
817 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
818
819 phys_addr.u.a64.address =
820 *((unsigned long long *)(&phys_addr.u.a64.address));
821
822 switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32]
823 & PDUCQE_CODE_MASK) {
824 case UNSOL_HDR_NOTIFY:
825 is_header = 1;
826
827 pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
828 (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
829 index) / 32] & PDUCQE_INDEX_MASK));
830
831 buffer_len = (unsigned int)(phys_addr.u.a64.address -
832 pasync_ctx->async_header.pa_base.u.a64.address);
833
834 buffer_index = buffer_len /
835 pasync_ctx->async_header.buffer_size;
836
837 break;
838 case UNSOL_DATA_NOTIFY:
839 pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
840 dw[offsetof(struct amap_i_t_dpdu_cqe,
841 index) / 32] & PDUCQE_INDEX_MASK));
842 buffer_len = (unsigned long)(phys_addr.u.a64.address -
843 pasync_ctx->async_data.pa_base.u.
844 a64.address);
845 buffer_index = buffer_len / pasync_ctx->async_data.buffer_size;
846 break;
847 default:
848 pbusy_list = NULL;
849 shost_printk(KERN_WARNING, phba->shost,
850 "Unexpected code=%d \n",
851 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
852 code) / 32] & PDUCQE_CODE_MASK);
853 return NULL;
854 }
855
856 WARN_ON(!(buffer_index <= pasync_ctx->async_data.num_entries));
857 WARN_ON(list_empty(pbusy_list));
858 list_for_each_entry(pasync_handle, pbusy_list, link) {
859 WARN_ON(pasync_handle->consumed);
860 if (pasync_handle->index == buffer_index)
861 break;
862 }
863
864 WARN_ON(!pasync_handle);
865
866 pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid;
867 pasync_handle->is_header = is_header;
868 pasync_handle->buffer_len = ((pdpdu_cqe->
869 dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
870 & PDUCQE_DPL_MASK) >> 16);
871
872 *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
873 index) / 32] & PDUCQE_INDEX_MASK);
874 return pasync_handle;
875}
876
877static unsigned int
878hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,
879 unsigned int is_header, unsigned int cq_index)
880{
881 struct list_head *pbusy_list;
882 struct async_pdu_handle *pasync_handle;
883 unsigned int num_entries, writables = 0;
884 unsigned int *pep_read_ptr, *pwritables;
885
886
887 if (is_header) {
888 pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr;
889 pwritables = &pasync_ctx->async_header.writables;
890 num_entries = pasync_ctx->async_header.num_entries;
891 } else {
892 pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr;
893 pwritables = &pasync_ctx->async_data.writables;
894 num_entries = pasync_ctx->async_data.num_entries;
895 }
896
897 while ((*pep_read_ptr) != cq_index) {
898 (*pep_read_ptr)++;
899 *pep_read_ptr = (*pep_read_ptr) % num_entries;
900
901 pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header,
902 *pep_read_ptr);
903 if (writables == 0)
904 WARN_ON(list_empty(pbusy_list));
905
906 if (!list_empty(pbusy_list)) {
907 pasync_handle = list_entry(pbusy_list->next,
908 struct async_pdu_handle,
909 link);
910 WARN_ON(!pasync_handle);
911 pasync_handle->consumed = 1;
912 }
913
914 writables++;
915 }
916
917 if (!writables) {
918 SE_DEBUG(DBG_LVL_1,
919 "Duplicate notification received - index 0x%x!!\n",
920 cq_index);
921 WARN_ON(1);
922 }
923
924 *pwritables = *pwritables + writables;
925 return 0;
926}
927
928static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba,
929 unsigned int cri)
930{
931 struct hwi_controller *phwi_ctrlr;
932 struct hwi_async_pdu_context *pasync_ctx;
933 struct async_pdu_handle *pasync_handle, *tmp_handle;
934 struct list_head *plist;
935 unsigned int i = 0;
936
937 phwi_ctrlr = phba->phwi_ctrlr;
938 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
939
940 plist = &pasync_ctx->async_entry[cri].wait_queue.list;
941
942 list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
943 list_del(&pasync_handle->link);
944
945 if (i == 0) {
946 list_add_tail(&pasync_handle->link,
947 &pasync_ctx->async_header.free_list);
948 pasync_ctx->async_header.free_entries++;
949 i++;
950 } else {
951 list_add_tail(&pasync_handle->link,
952 &pasync_ctx->async_data.free_list);
953 pasync_ctx->async_data.free_entries++;
954 i++;
955 }
956 }
957
958 INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list);
959 pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0;
960 pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
961 return 0;
962}
963
964static struct phys_addr *
965hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx,
966 unsigned int is_header, unsigned int host_write_ptr)
967{
968 struct phys_addr *pasync_sge = NULL;
969
970 if (is_header)
971 pasync_sge = pasync_ctx->async_header.ring_base;
972 else
973 pasync_sge = pasync_ctx->async_data.ring_base;
974
975 return pasync_sge + host_write_ptr;
976}
977
978static void hwi_post_async_buffers(struct beiscsi_hba *phba,
979 unsigned int is_header)
980{
981 struct hwi_controller *phwi_ctrlr;
982 struct hwi_async_pdu_context *pasync_ctx;
983 struct async_pdu_handle *pasync_handle;
984 struct list_head *pfree_link, *pbusy_list;
985 struct phys_addr *pasync_sge;
986 unsigned int ring_id, num_entries;
987 unsigned int host_write_num;
988 unsigned int writables;
989 unsigned int i = 0;
990 u32 doorbell = 0;
991
992 phwi_ctrlr = phba->phwi_ctrlr;
993 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
994
995 if (is_header) {
996 num_entries = pasync_ctx->async_header.num_entries;
997 writables = min(pasync_ctx->async_header.writables,
998 pasync_ctx->async_header.free_entries);
999 pfree_link = pasync_ctx->async_header.free_list.next;
1000 host_write_num = pasync_ctx->async_header.host_write_ptr;
1001 ring_id = phwi_ctrlr->default_pdu_hdr.id;
1002 } else {
1003 num_entries = pasync_ctx->async_data.num_entries;
1004 writables = min(pasync_ctx->async_data.writables,
1005 pasync_ctx->async_data.free_entries);
1006 pfree_link = pasync_ctx->async_data.free_list.next;
1007 host_write_num = pasync_ctx->async_data.host_write_ptr;
1008 ring_id = phwi_ctrlr->default_pdu_data.id;
1009 }
1010
1011 writables = (writables / 8) * 8;
1012 if (writables) {
1013 for (i = 0; i < writables; i++) {
1014 pbusy_list =
1015 hwi_get_async_busy_list(pasync_ctx, is_header,
1016 host_write_num);
1017 pasync_handle =
1018 list_entry(pfree_link, struct async_pdu_handle,
1019 link);
1020 WARN_ON(!pasync_handle);
1021 pasync_handle->consumed = 0;
1022
1023 pfree_link = pfree_link->next;
1024
1025 pasync_sge = hwi_get_ring_address(pasync_ctx,
1026 is_header, host_write_num);
1027
1028 pasync_sge->hi = pasync_handle->pa.u.a32.address_lo;
1029 pasync_sge->lo = pasync_handle->pa.u.a32.address_hi;
1030
1031 list_move(&pasync_handle->link, pbusy_list);
1032
1033 host_write_num++;
1034 host_write_num = host_write_num % num_entries;
1035 }
1036
1037 if (is_header) {
1038 pasync_ctx->async_header.host_write_ptr =
1039 host_write_num;
1040 pasync_ctx->async_header.free_entries -= writables;
1041 pasync_ctx->async_header.writables -= writables;
1042 pasync_ctx->async_header.busy_entries += writables;
1043 } else {
1044 pasync_ctx->async_data.host_write_ptr = host_write_num;
1045 pasync_ctx->async_data.free_entries -= writables;
1046 pasync_ctx->async_data.writables -= writables;
1047 pasync_ctx->async_data.busy_entries += writables;
1048 }
1049
1050 doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK;
1051 doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT;
1052 doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT;
1053 doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK)
1054 << DB_DEF_PDU_CQPROC_SHIFT;
1055
1056 iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET);
1057 }
1058}
1059
1060static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba,
1061 struct beiscsi_conn *beiscsi_conn,
1062 struct i_t_dpdu_cqe *pdpdu_cqe)
1063{
1064 struct hwi_controller *phwi_ctrlr;
1065 struct hwi_async_pdu_context *pasync_ctx;
1066 struct async_pdu_handle *pasync_handle = NULL;
1067 unsigned int cq_index = -1;
1068
1069 phwi_ctrlr = phba->phwi_ctrlr;
1070 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1071
1072 pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
1073 pdpdu_cqe, &cq_index);
1074 BUG_ON(pasync_handle->is_header != 0);
1075 if (pasync_handle->consumed == 0)
1076 hwi_update_async_writables(pasync_ctx, pasync_handle->is_header,
1077 cq_index);
1078
1079 hwi_free_async_msg(phba, pasync_handle->cri);
1080 hwi_post_async_buffers(phba, pasync_handle->is_header);
1081}
1082
1083static unsigned int
1084hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
1085 struct beiscsi_hba *phba,
1086 struct hwi_async_pdu_context *pasync_ctx, unsigned short cri)
1087{
1088 struct list_head *plist;
1089 struct async_pdu_handle *pasync_handle;
1090 void *phdr = NULL;
1091 unsigned int hdr_len = 0, buf_len = 0;
1092 unsigned int status, index = 0, offset = 0;
1093 void *pfirst_buffer = NULL;
1094 unsigned int num_buf = 0;
1095
1096 plist = &pasync_ctx->async_entry[cri].wait_queue.list;
1097
1098 list_for_each_entry(pasync_handle, plist, link) {
1099 if (index == 0) {
1100 phdr = pasync_handle->pbuffer;
1101 hdr_len = pasync_handle->buffer_len;
1102 } else {
1103 buf_len = pasync_handle->buffer_len;
1104 if (!num_buf) {
1105 pfirst_buffer = pasync_handle->pbuffer;
1106 num_buf++;
1107 }
1108 memcpy(pfirst_buffer + offset,
1109 pasync_handle->pbuffer, buf_len);
1110 offset = buf_len;
1111 }
1112 index++;
1113 }
1114
1115 status = beiscsi_process_async_pdu(beiscsi_conn, phba,
1116 beiscsi_conn->beiscsi_conn_cid,
1117 phdr, hdr_len, pfirst_buffer,
1118 buf_len);
1119
1120 if (status == 0)
1121 hwi_free_async_msg(phba, cri);
1122 return 0;
1123}
1124
1125static unsigned int
1126hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn,
1127 struct beiscsi_hba *phba,
1128 struct async_pdu_handle *pasync_handle)
1129{
1130 struct hwi_async_pdu_context *pasync_ctx;
1131 struct hwi_controller *phwi_ctrlr;
1132 unsigned int bytes_needed = 0, status = 0;
1133 unsigned short cri = pasync_handle->cri;
1134 struct pdu_base *ppdu;
1135
1136 phwi_ctrlr = phba->phwi_ctrlr;
1137 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1138
1139 list_del(&pasync_handle->link);
1140 if (pasync_handle->is_header) {
1141 pasync_ctx->async_header.busy_entries--;
1142 if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
1143 hwi_free_async_msg(phba, cri);
1144 BUG();
1145 }
1146
1147 pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
1148 pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1;
1149 pasync_ctx->async_entry[cri].wait_queue.hdr_len =
1150 (unsigned short)pasync_handle->buffer_len;
1151 list_add_tail(&pasync_handle->link,
1152 &pasync_ctx->async_entry[cri].wait_queue.list);
1153
1154 ppdu = pasync_handle->pbuffer;
1155 bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base,
1156 data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) &
1157 0xFFFF0000) | ((be16_to_cpu((ppdu->
1158 dw[offsetof(struct amap_pdu_base, data_len_lo) / 32]
1159 & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF));
1160
1161 if (status == 0) {
1162 pasync_ctx->async_entry[cri].wait_queue.bytes_needed =
1163 bytes_needed;
1164
1165 if (bytes_needed == 0)
1166 status = hwi_fwd_async_msg(beiscsi_conn, phba,
1167 pasync_ctx, cri);
1168 }
1169 } else {
1170 pasync_ctx->async_data.busy_entries--;
1171 if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
1172 list_add_tail(&pasync_handle->link,
1173 &pasync_ctx->async_entry[cri].wait_queue.
1174 list);
1175 pasync_ctx->async_entry[cri].wait_queue.
1176 bytes_received +=
1177 (unsigned short)pasync_handle->buffer_len;
1178
1179 if (pasync_ctx->async_entry[cri].wait_queue.
1180 bytes_received >=
1181 pasync_ctx->async_entry[cri].wait_queue.
1182 bytes_needed)
1183 status = hwi_fwd_async_msg(beiscsi_conn, phba,
1184 pasync_ctx, cri);
1185 }
1186 }
1187 return status;
1188}
1189
1190static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
1191 struct beiscsi_hba *phba,
1192 struct i_t_dpdu_cqe *pdpdu_cqe)
1193{
1194 struct hwi_controller *phwi_ctrlr;
1195 struct hwi_async_pdu_context *pasync_ctx;
1196 struct async_pdu_handle *pasync_handle = NULL;
1197 unsigned int cq_index = -1;
1198
1199 phwi_ctrlr = phba->phwi_ctrlr;
1200 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1201 pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
1202 pdpdu_cqe, &cq_index);
1203
1204 if (pasync_handle->consumed == 0)
1205 hwi_update_async_writables(pasync_ctx, pasync_handle->is_header,
1206 cq_index);
1207 hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle);
1208 hwi_post_async_buffers(phba, pasync_handle->is_header);
1209}
1210
1211static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba)
1212{
1213 struct hwi_controller *phwi_ctrlr;
1214 struct hwi_context_memory *phwi_context;
1215 struct be_queue_info *cq;
1216 struct sol_cqe *sol;
1217 struct dmsg_cqe *dmsg;
1218 unsigned int num_processed = 0;
1219 unsigned int tot_nump = 0;
1220 struct beiscsi_conn *beiscsi_conn;
1221
1222 phwi_ctrlr = phba->phwi_ctrlr;
1223 phwi_context = phwi_ctrlr->phwi_ctxt;
1224 cq = &phwi_context->be_cq;
1225 sol = queue_tail_node(cq);
1226
1227 while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] &
1228 CQE_VALID_MASK) {
1229 be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
1230
1231 beiscsi_conn = phba->conn_table[(u32) (sol->
1232 dw[offsetof(struct amap_sol_cqe, cid) / 32] &
1233 SOL_CID_MASK) >> 6];
1234
1235 if (!beiscsi_conn || !beiscsi_conn->ep) {
1236 shost_printk(KERN_WARNING, phba->shost,
1237 "Connection table empty for cid = %d\n",
1238 (u32)(sol->dw[offsetof(struct amap_sol_cqe,
1239 cid) / 32] & SOL_CID_MASK) >> 6);
1240 return 0;
1241 }
1242
1243 if (num_processed >= 32) {
1244 hwi_ring_cq_db(phba, phwi_context->be_cq.id,
1245 num_processed, 0, 0);
1246 tot_nump += num_processed;
1247 num_processed = 0;
1248 }
1249
1250 switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) /
1251 32] & CQE_CODE_MASK) {
1252 case SOL_CMD_COMPLETE:
1253 hwi_complete_cmd(beiscsi_conn, phba, sol);
1254 break;
1255 case DRIVERMSG_NOTIFY:
1256 SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY \n");
1257 dmsg = (struct dmsg_cqe *)sol;
1258 hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
1259 break;
1260 case UNSOL_HDR_NOTIFY:
1261 case UNSOL_DATA_NOTIFY:
1262 SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR/DATA_NOTIFY\n");
1263 hwi_process_default_pdu_ring(beiscsi_conn, phba,
1264 (struct i_t_dpdu_cqe *)sol);
1265 break;
1266 case CXN_INVALIDATE_INDEX_NOTIFY:
1267 case CMD_INVALIDATED_NOTIFY:
1268 case CXN_INVALIDATE_NOTIFY:
1269 SE_DEBUG(DBG_LVL_1,
1270 "Ignoring CQ Error notification for cmd/cxn"
1271 "invalidate\n");
1272 break;
1273 case SOL_CMD_KILLED_DATA_DIGEST_ERR:
1274 case CMD_KILLED_INVALID_STATSN_RCVD:
1275 case CMD_KILLED_INVALID_R2T_RCVD:
1276 case CMD_CXN_KILLED_LUN_INVALID:
1277 case CMD_CXN_KILLED_ICD_INVALID:
1278 case CMD_CXN_KILLED_ITT_INVALID:
1279 case CMD_CXN_KILLED_SEQ_OUTOFORDER:
1280 case CMD_CXN_KILLED_INVALID_DATASN_RCVD:
1281 SE_DEBUG(DBG_LVL_1,
1282 "CQ Error notification for cmd.. "
1283 "code %d cid 0x%x\n",
1284 sol->dw[offsetof(struct amap_sol_cqe, code) /
1285 32] & CQE_CODE_MASK,
1286 (sol->dw[offsetof(struct amap_sol_cqe, cid) /
1287 32] & SOL_CID_MASK));
1288 break;
1289 case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
1290 SE_DEBUG(DBG_LVL_1,
1291 "Digest error on def pdu ring, dropping..\n");
1292 hwi_flush_default_pdu_buffer(phba, beiscsi_conn,
1293 (struct i_t_dpdu_cqe *) sol);
1294 break;
1295 case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL:
1296 case CXN_KILLED_BURST_LEN_MISMATCH:
1297 case CXN_KILLED_AHS_RCVD:
1298 case CXN_KILLED_HDR_DIGEST_ERR:
1299 case CXN_KILLED_UNKNOWN_HDR:
1300 case CXN_KILLED_STALE_ITT_TTT_RCVD:
1301 case CXN_KILLED_INVALID_ITT_TTT_RCVD:
1302 case CXN_KILLED_TIMED_OUT:
1303 case CXN_KILLED_FIN_RCVD:
1304 case CXN_KILLED_BAD_UNSOL_PDU_RCVD:
1305 case CXN_KILLED_BAD_WRB_INDEX_ERROR:
1306 case CXN_KILLED_OVER_RUN_RESIDUAL:
1307 case CXN_KILLED_UNDER_RUN_RESIDUAL:
1308 case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
1309 SE_DEBUG(DBG_LVL_1, "CQ Error %d, resetting CID "
1310 "0x%x...\n",
1311 sol->dw[offsetof(struct amap_sol_cqe, code) /
1312 32] & CQE_CODE_MASK,
1313 sol->dw[offsetof(struct amap_sol_cqe, cid) /
1314 32] & CQE_CID_MASK);
1315 iscsi_conn_failure(beiscsi_conn->conn,
1316 ISCSI_ERR_CONN_FAILED);
1317 break;
1318 case CXN_KILLED_RST_SENT:
1319 case CXN_KILLED_RST_RCVD:
1320 SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset received/sent "
1321 "on CID 0x%x...\n",
1322 sol->dw[offsetof(struct amap_sol_cqe, code) /
1323 32] & CQE_CODE_MASK,
1324 sol->dw[offsetof(struct amap_sol_cqe, cid) /
1325 32] & CQE_CID_MASK);
1326 iscsi_conn_failure(beiscsi_conn->conn,
1327 ISCSI_ERR_CONN_FAILED);
1328 break;
1329 default:
1330 SE_DEBUG(DBG_LVL_1, "CQ Error Invalid code= %d "
1331 "received on CID 0x%x...\n",
1332 sol->dw[offsetof(struct amap_sol_cqe, code) /
1333 32] & CQE_CODE_MASK,
1334 sol->dw[offsetof(struct amap_sol_cqe, cid) /
1335 32] & CQE_CID_MASK);
1336 break;
1337 }
1338
1339 AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0);
1340 queue_tail_inc(cq);
1341 sol = queue_tail_node(cq);
1342 num_processed++;
1343 }
1344
1345 if (num_processed > 0) {
1346 tot_nump += num_processed;
1347 hwi_ring_cq_db(phba, phwi_context->be_cq.id, num_processed,
1348 1, 0);
1349 }
1350 return tot_nump;
1351}
1352
1353static void beiscsi_process_all_cqs(struct work_struct *work)
1354{
1355 unsigned long flags;
1356 struct beiscsi_hba *phba =
1357 container_of(work, struct beiscsi_hba, work_cqs);
1358
1359 if (phba->todo_mcc_cq) {
1360 spin_lock_irqsave(&phba->isr_lock, flags);
1361 phba->todo_mcc_cq = 0;
1362 spin_unlock_irqrestore(&phba->isr_lock, flags);
1363 SE_DEBUG(DBG_LVL_1, "MCC Interrupt Not expected \n");
1364 }
1365
1366 if (phba->todo_cq) {
1367 spin_lock_irqsave(&phba->isr_lock, flags);
1368 phba->todo_cq = 0;
1369 spin_unlock_irqrestore(&phba->isr_lock, flags);
1370 beiscsi_process_cq(phba);
1371 }
1372}
1373
1374static int be_iopoll(struct blk_iopoll *iop, int budget)
1375{
1376 static unsigned int ret;
1377 struct beiscsi_hba *phba;
1378
1379 phba = container_of(iop, struct beiscsi_hba, iopoll);
1380
1381 ret = beiscsi_process_cq(phba);
1382 if (ret < budget) {
1383 struct hwi_controller *phwi_ctrlr;
1384 struct hwi_context_memory *phwi_context;
1385
1386 phwi_ctrlr = phba->phwi_ctrlr;
1387 phwi_context = phwi_ctrlr->phwi_ctxt;
1388 blk_iopoll_complete(iop);
1389 hwi_ring_eq_db(phba, phwi_context->be_eq.q.id, 0,
1390 0, 1, 1);
1391 }
1392 return ret;
1393}
1394
1395static void
1396hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
1397 unsigned int num_sg, struct beiscsi_io_task *io_task)
1398{
1399 struct iscsi_sge *psgl;
1400 unsigned short sg_len, index;
1401 unsigned int sge_len = 0;
1402 unsigned long long addr;
1403 struct scatterlist *l_sg;
1404 unsigned int offset;
1405
1406 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
1407 io_task->bhs_pa.u.a32.address_lo);
1408 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
1409 io_task->bhs_pa.u.a32.address_hi);
1410
1411 l_sg = sg;
1412 for (index = 0; (index < num_sg) && (index < 2); index++, sg_next(sg)) {
1413 if (index == 0) {
1414 sg_len = sg_dma_len(sg);
1415 addr = (u64) sg_dma_address(sg);
1416 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
1417 (addr & 0xFFFFFFFF));
1418 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
1419 (addr >> 32));
1420 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
1421 sg_len);
1422 sge_len = sg_len;
1423 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
1424 1);
1425 } else {
1426 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
1427 0);
1428 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset,
1429 pwrb, sge_len);
1430 sg_len = sg_dma_len(sg);
1431 addr = (u64) sg_dma_address(sg);
1432 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb,
1433 (addr & 0xFFFFFFFF));
1434 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb,
1435 (addr >> 32));
1436 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb,
1437 sg_len);
1438 }
1439 }
1440 psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
1441 memset(psgl, 0, sizeof(*psgl) * BE2_SGE);
1442
1443 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2);
1444
1445 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
1446 io_task->bhs_pa.u.a32.address_hi);
1447 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
1448 io_task->bhs_pa.u.a32.address_lo);
1449
1450 if (num_sg == 2)
1451 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 1);
1452 sg = l_sg;
1453 psgl++;
1454 psgl++;
1455 offset = 0;
1456 for (index = 0; index < num_sg; index++, sg_next(sg), psgl++) {
1457 sg_len = sg_dma_len(sg);
1458 addr = (u64) sg_dma_address(sg);
1459 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
1460 (addr & 0xFFFFFFFF));
1461 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
1462 (addr >> 32));
1463 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len);
1464 AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset);
1465 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
1466 offset += sg_len;
1467 }
1468 psgl--;
1469 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
1470}
1471
1472static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
1473{
1474 struct iscsi_sge *psgl;
1475 unsigned long long addr;
1476 struct beiscsi_io_task *io_task = task->dd_data;
1477 struct beiscsi_conn *beiscsi_conn = io_task->conn;
1478 struct beiscsi_hba *phba = beiscsi_conn->phba;
1479
1480 io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;
1481 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
1482 io_task->bhs_pa.u.a32.address_lo);
1483 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
1484 io_task->bhs_pa.u.a32.address_hi);
1485
1486 if (task->data) {
1487 if (task->data_count) {
1488 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
1489 addr = (u64) pci_map_single(phba->pcidev,
1490 task->data,
1491 task->data_count, 1);
1492 } else {
1493 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
1494 addr = 0;
1495 }
1496 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
1497 (addr & 0xFFFFFFFF));
1498 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
1499 (addr >> 32));
1500 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
1501 task->data_count);
1502
1503 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);
1504 } else {
1505 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
1506 addr = 0;
1507 }
1508
1509 psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
1510
1511 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len);
1512
1513 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
1514 io_task->bhs_pa.u.a32.address_hi);
1515 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
1516 io_task->bhs_pa.u.a32.address_lo);
1517 if (task->data) {
1518 psgl++;
1519 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 0);
1520 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 0);
1521 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0);
1522 AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, 0);
1523 AMAP_SET_BITS(struct amap_iscsi_sge, rsvd0, psgl, 0);
1524 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
1525
1526 psgl++;
1527 if (task->data) {
1528 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
1529 (addr & 0xFFFFFFFF));
1530 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
1531 (addr >> 32));
1532 }
1533 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
1534 }
1535 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
1536}
1537
1538static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
1539{
1540 unsigned int num_cq_pages, num_eq_pages, num_async_pdu_buf_pages;
1541 unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;
1542 unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;
1543
1544 num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
1545 sizeof(struct sol_cqe));
1546 num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
1547 sizeof(struct be_eq_entry));
1548 num_async_pdu_buf_pages =
1549 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
1550 phba->params.defpdu_hdr_sz);
1551 num_async_pdu_buf_sgl_pages =
1552 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
1553 sizeof(struct phys_addr));
1554 num_async_pdu_data_pages =
1555 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
1556 phba->params.defpdu_data_sz);
1557 num_async_pdu_data_sgl_pages =
1558 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
1559 sizeof(struct phys_addr));
1560
1561 phba->params.hwi_ws_sz = sizeof(struct hwi_controller);
1562
1563 phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 *
1564 BE_ISCSI_PDU_HEADER_SIZE;
1565 phba->mem_req[HWI_MEM_ADDN_CONTEXT] =
1566 sizeof(struct hwi_context_memory);
1567
1568 phba->mem_req[HWI_MEM_CQ] = num_cq_pages * PAGE_SIZE;
1569 phba->mem_req[HWI_MEM_EQ] = num_eq_pages * PAGE_SIZE;
1570
1571 phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb)
1572 * (phba->params.wrbs_per_cxn)
1573 * phba->params.cxns_per_ctrl;
1574 wrb_sz_per_cxn = sizeof(struct wrb_handle) *
1575 (phba->params.wrbs_per_cxn);
1576 phba->mem_req[HWI_MEM_WRBH] = roundup_pow_of_two((wrb_sz_per_cxn) *
1577 phba->params.cxns_per_ctrl);
1578
1579 phba->mem_req[HWI_MEM_SGLH] = sizeof(struct sgl_handle) *
1580 phba->params.icds_per_ctrl;
1581 phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) *
1582 phba->params.num_sge_per_io * phba->params.icds_per_ctrl;
1583
1584 phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] =
1585 num_async_pdu_buf_pages * PAGE_SIZE;
1586 phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] =
1587 num_async_pdu_data_pages * PAGE_SIZE;
1588 phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] =
1589 num_async_pdu_buf_sgl_pages * PAGE_SIZE;
1590 phba->mem_req[HWI_MEM_ASYNC_DATA_RING] =
1591 num_async_pdu_data_sgl_pages * PAGE_SIZE;
1592 phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] =
1593 phba->params.asyncpdus_per_ctrl *
1594 sizeof(struct async_pdu_handle);
1595 phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] =
1596 phba->params.asyncpdus_per_ctrl *
1597 sizeof(struct async_pdu_handle);
1598 phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] =
1599 sizeof(struct hwi_async_pdu_context) +
1600 (phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry));
1601}
1602
1603static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
1604{
1605 struct be_mem_descriptor *mem_descr;
1606 dma_addr_t bus_add;
1607 struct mem_array *mem_arr, *mem_arr_orig;
1608 unsigned int i, j, alloc_size, curr_alloc_size;
1609
1610 phba->phwi_ctrlr = kmalloc(phba->params.hwi_ws_sz, GFP_KERNEL);
1611 if (!phba->phwi_ctrlr)
1612 return -ENOMEM;
1613
1614 phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
1615 GFP_KERNEL);
1616 if (!phba->init_mem) {
1617 kfree(phba->phwi_ctrlr);
1618 return -ENOMEM;
1619 }
1620
1621 mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT,
1622 GFP_KERNEL);
1623 if (!mem_arr_orig) {
1624 kfree(phba->init_mem);
1625 kfree(phba->phwi_ctrlr);
1626 return -ENOMEM;
1627 }
1628
1629 mem_descr = phba->init_mem;
1630 for (i = 0; i < SE_MEM_MAX; i++) {
1631 j = 0;
1632 mem_arr = mem_arr_orig;
1633 alloc_size = phba->mem_req[i];
1634 memset(mem_arr, 0, sizeof(struct mem_array) *
1635 BEISCSI_MAX_FRAGS_INIT);
1636 curr_alloc_size = min(be_max_phys_size * 1024, alloc_size);
1637 do {
1638 mem_arr->virtual_address = pci_alloc_consistent(
1639 phba->pcidev,
1640 curr_alloc_size,
1641 &bus_add);
1642 if (!mem_arr->virtual_address) {
1643 if (curr_alloc_size <= BE_MIN_MEM_SIZE)
1644 goto free_mem;
1645 if (curr_alloc_size -
1646 rounddown_pow_of_two(curr_alloc_size))
1647 curr_alloc_size = rounddown_pow_of_two
1648 (curr_alloc_size);
1649 else
1650 curr_alloc_size = curr_alloc_size / 2;
1651 } else {
1652 mem_arr->bus_address.u.
1653 a64.address = (__u64) bus_add;
1654 mem_arr->size = curr_alloc_size;
1655 alloc_size -= curr_alloc_size;
1656 curr_alloc_size = min(be_max_phys_size *
1657 1024, alloc_size);
1658 j++;
1659 mem_arr++;
1660 }
1661 } while (alloc_size);
1662 mem_descr->num_elements = j;
1663 mem_descr->size_in_bytes = phba->mem_req[i];
1664 mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j,
1665 GFP_KERNEL);
1666 if (!mem_descr->mem_array)
1667 goto free_mem;
1668
1669 memcpy(mem_descr->mem_array, mem_arr_orig,
1670 sizeof(struct mem_array) * j);
1671 mem_descr++;
1672 }
1673 kfree(mem_arr_orig);
1674 return 0;
1675free_mem:
1676 mem_descr->num_elements = j;
1677 while ((i) || (j)) {
1678 for (j = mem_descr->num_elements; j > 0; j--) {
1679 pci_free_consistent(phba->pcidev,
1680 mem_descr->mem_array[j - 1].size,
1681 mem_descr->mem_array[j - 1].
1682 virtual_address,
1683 mem_descr->mem_array[j - 1].
1684 bus_address.u.a64.address);
1685 }
1686 if (i) {
1687 i--;
1688 kfree(mem_descr->mem_array);
1689 mem_descr--;
1690 }
1691 }
1692 kfree(mem_arr_orig);
1693 kfree(phba->init_mem);
1694 kfree(phba->phwi_ctrlr);
1695 return -ENOMEM;
1696}
1697
1698static int beiscsi_get_memory(struct beiscsi_hba *phba)
1699{
1700 beiscsi_find_mem_req(phba);
1701 return beiscsi_alloc_mem(phba);
1702}
1703
1704static void iscsi_init_global_templates(struct beiscsi_hba *phba)
1705{
1706 struct pdu_data_out *pdata_out;
1707 struct pdu_nop_out *pnop_out;
1708 struct be_mem_descriptor *mem_descr;
1709
1710 mem_descr = phba->init_mem;
1711 mem_descr += ISCSI_MEM_GLOBAL_HEADER;
1712 pdata_out =
1713 (struct pdu_data_out *)mem_descr->mem_array[0].virtual_address;
1714 memset(pdata_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
1715
1716 AMAP_SET_BITS(struct amap_pdu_data_out, opcode, pdata_out,
1717 IIOC_SCSI_DATA);
1718
1719 pnop_out =
1720 (struct pdu_nop_out *)((unsigned char *)mem_descr->mem_array[0].
1721 virtual_address + BE_ISCSI_PDU_HEADER_SIZE);
1722
1723 memset(pnop_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
1724 AMAP_SET_BITS(struct amap_pdu_nop_out, ttt, pnop_out, 0xFFFFFFFF);
1725 AMAP_SET_BITS(struct amap_pdu_nop_out, f_bit, pnop_out, 1);
1726 AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0);
1727}
1728
1729static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
1730{
1731 struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
1732 struct wrb_handle *pwrb_handle;
1733 struct hwi_controller *phwi_ctrlr;
1734 struct hwi_wrb_context *pwrb_context;
1735 struct iscsi_wrb *pwrb;
1736 unsigned int num_cxn_wrbh;
1737 unsigned int num_cxn_wrb, j, idx, index;
1738
1739 mem_descr_wrbh = phba->init_mem;
1740 mem_descr_wrbh += HWI_MEM_WRBH;
1741
1742 mem_descr_wrb = phba->init_mem;
1743 mem_descr_wrb += HWI_MEM_WRB;
1744
1745 idx = 0;
1746 pwrb_handle = mem_descr_wrbh->mem_array[idx].virtual_address;
1747 num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) /
1748 ((sizeof(struct wrb_handle)) *
1749 phba->params.wrbs_per_cxn));
1750 phwi_ctrlr = phba->phwi_ctrlr;
1751
1752 for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
1753 pwrb_context = &phwi_ctrlr->wrb_context[index];
1754 SE_DEBUG(DBG_LVL_8, "cid=%d pwrb_context=%p \n", index,
1755 pwrb_context);
1756 pwrb_context->pwrb_handle_base =
1757 kzalloc(sizeof(struct wrb_handle *) *
1758 phba->params.wrbs_per_cxn, GFP_KERNEL);
1759 pwrb_context->pwrb_handle_basestd =
1760 kzalloc(sizeof(struct wrb_handle *) *
1761 phba->params.wrbs_per_cxn, GFP_KERNEL);
1762 if (num_cxn_wrbh) {
1763 pwrb_context->alloc_index = 0;
1764 pwrb_context->wrb_handles_available = 0;
1765 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
1766 pwrb_context->pwrb_handle_base[j] = pwrb_handle;
1767 pwrb_context->pwrb_handle_basestd[j] =
1768 pwrb_handle;
1769 pwrb_context->wrb_handles_available++;
1770 pwrb_handle++;
1771 }
1772 pwrb_context->free_index = 0;
1773 num_cxn_wrbh--;
1774 } else {
1775 idx++;
1776 pwrb_handle =
1777 mem_descr_wrbh->mem_array[idx].virtual_address;
1778 num_cxn_wrbh =
1779 ((mem_descr_wrbh->mem_array[idx].size) /
1780 ((sizeof(struct wrb_handle)) *
1781 phba->params.wrbs_per_cxn));
1782 pwrb_context->alloc_index = 0;
1783 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
1784 pwrb_context->pwrb_handle_base[j] = pwrb_handle;
1785 pwrb_context->pwrb_handle_basestd[j] =
1786 pwrb_handle;
1787 pwrb_context->wrb_handles_available++;
1788 pwrb_handle++;
1789 }
1790 pwrb_context->free_index = 0;
1791 num_cxn_wrbh--;
1792 }
1793 }
1794 idx = 0;
1795 pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
1796 num_cxn_wrb =
1797 ((mem_descr_wrb->mem_array[idx].size) / (sizeof(struct iscsi_wrb)) *
1798 phba->params.wrbs_per_cxn);
1799
1800 for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) {
1801 pwrb_context = &phwi_ctrlr->wrb_context[index];
1802 if (num_cxn_wrb) {
1803 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
1804 pwrb_handle = pwrb_context->pwrb_handle_base[j];
1805 pwrb_handle->pwrb = pwrb;
1806 pwrb++;
1807 }
1808 num_cxn_wrb--;
1809 } else {
1810 idx++;
1811 pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
1812 num_cxn_wrb = ((mem_descr_wrb->mem_array[idx].size) /
1813 (sizeof(struct iscsi_wrb)) *
1814 phba->params.wrbs_per_cxn);
1815 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
1816 pwrb_handle = pwrb_context->pwrb_handle_base[j];
1817 pwrb_handle->pwrb = pwrb;
1818 pwrb++;
1819 }
1820 num_cxn_wrb--;
1821 }
1822 }
1823}
1824
1825static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
1826{
1827 struct hwi_controller *phwi_ctrlr;
1828 struct hba_parameters *p = &phba->params;
1829 struct hwi_async_pdu_context *pasync_ctx;
1830 struct async_pdu_handle *pasync_header_h, *pasync_data_h;
1831 unsigned int index;
1832 struct be_mem_descriptor *mem_descr;
1833
1834 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1835 mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT;
1836
1837 phwi_ctrlr = phba->phwi_ctrlr;
1838 phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *)
1839 mem_descr->mem_array[0].virtual_address;
1840 pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
1841 memset(pasync_ctx, 0, sizeof(*pasync_ctx));
1842
1843 pasync_ctx->async_header.num_entries = p->asyncpdus_per_ctrl;
1844 pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz;
1845 pasync_ctx->async_data.buffer_size = p->defpdu_data_sz;
1846 pasync_ctx->async_data.num_entries = p->asyncpdus_per_ctrl;
1847
1848 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1849 mem_descr += HWI_MEM_ASYNC_HEADER_BUF;
1850 if (mem_descr->mem_array[0].virtual_address) {
1851 SE_DEBUG(DBG_LVL_8,
1852 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF"
1853 "va=%p \n", mem_descr->mem_array[0].virtual_address);
1854 } else
1855 shost_printk(KERN_WARNING, phba->shost,
1856 "No Virtual address \n");
1857
1858 pasync_ctx->async_header.va_base =
1859 mem_descr->mem_array[0].virtual_address;
1860
1861 pasync_ctx->async_header.pa_base.u.a64.address =
1862 mem_descr->mem_array[0].bus_address.u.a64.address;
1863
1864 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1865 mem_descr += HWI_MEM_ASYNC_HEADER_RING;
1866 if (mem_descr->mem_array[0].virtual_address) {
1867 SE_DEBUG(DBG_LVL_8,
1868 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING"
1869 "va=%p \n", mem_descr->mem_array[0].virtual_address);
1870 } else
1871 shost_printk(KERN_WARNING, phba->shost,
1872 "No Virtual address \n");
1873 pasync_ctx->async_header.ring_base =
1874 mem_descr->mem_array[0].virtual_address;
1875
1876 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1877 mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE;
1878 if (mem_descr->mem_array[0].virtual_address) {
1879 SE_DEBUG(DBG_LVL_8,
1880 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE"
1881 "va=%p \n", mem_descr->mem_array[0].virtual_address);
1882 } else
1883 shost_printk(KERN_WARNING, phba->shost,
1884 "No Virtual address \n");
1885
1886 pasync_ctx->async_header.handle_base =
1887 mem_descr->mem_array[0].virtual_address;
1888 pasync_ctx->async_header.writables = 0;
1889 INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
1890
1891 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1892 mem_descr += HWI_MEM_ASYNC_DATA_BUF;
1893 if (mem_descr->mem_array[0].virtual_address) {
1894 SE_DEBUG(DBG_LVL_8,
1895 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF"
1896 "va=%p \n", mem_descr->mem_array[0].virtual_address);
1897 } else
1898 shost_printk(KERN_WARNING, phba->shost,
1899 "No Virtual address \n");
1900 pasync_ctx->async_data.va_base =
1901 mem_descr->mem_array[0].virtual_address;
1902 pasync_ctx->async_data.pa_base.u.a64.address =
1903 mem_descr->mem_array[0].bus_address.u.a64.address;
1904
1905 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1906 mem_descr += HWI_MEM_ASYNC_DATA_RING;
1907 if (mem_descr->mem_array[0].virtual_address) {
1908 SE_DEBUG(DBG_LVL_8,
1909 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING"
1910 "va=%p \n", mem_descr->mem_array[0].virtual_address);
1911 } else
1912 shost_printk(KERN_WARNING, phba->shost,
1913 "No Virtual address \n");
1914
1915 pasync_ctx->async_data.ring_base =
1916 mem_descr->mem_array[0].virtual_address;
1917
1918 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
1919 mem_descr += HWI_MEM_ASYNC_DATA_HANDLE;
1920 if (!mem_descr->mem_array[0].virtual_address)
1921 shost_printk(KERN_WARNING, phba->shost,
1922 "No Virtual address \n");
1923
1924 pasync_ctx->async_data.handle_base =
1925 mem_descr->mem_array[0].virtual_address;
1926 pasync_ctx->async_data.writables = 0;
1927 INIT_LIST_HEAD(&pasync_ctx->async_data.free_list);
1928
1929 pasync_header_h =
1930 (struct async_pdu_handle *)pasync_ctx->async_header.handle_base;
1931 pasync_data_h =
1932 (struct async_pdu_handle *)pasync_ctx->async_data.handle_base;
1933
1934 for (index = 0; index < p->asyncpdus_per_ctrl; index++) {
1935 pasync_header_h->cri = -1;
1936 pasync_header_h->index = (char)index;
1937 INIT_LIST_HEAD(&pasync_header_h->link);
1938 pasync_header_h->pbuffer =
1939 (void *)((unsigned long)
1940 (pasync_ctx->async_header.va_base) +
1941 (p->defpdu_hdr_sz * index));
1942
1943 pasync_header_h->pa.u.a64.address =
1944 pasync_ctx->async_header.pa_base.u.a64.address +
1945 (p->defpdu_hdr_sz * index);
1946
1947 list_add_tail(&pasync_header_h->link,
1948 &pasync_ctx->async_header.free_list);
1949 pasync_header_h++;
1950 pasync_ctx->async_header.free_entries++;
1951 pasync_ctx->async_header.writables++;
1952
1953 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list);
1954 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].
1955 header_busy_list);
1956 pasync_data_h->cri = -1;
1957 pasync_data_h->index = (char)index;
1958 INIT_LIST_HEAD(&pasync_data_h->link);
1959 pasync_data_h->pbuffer =
1960 (void *)((unsigned long)
1961 (pasync_ctx->async_data.va_base) +
1962 (p->defpdu_data_sz * index));
1963
1964 pasync_data_h->pa.u.a64.address =
1965 pasync_ctx->async_data.pa_base.u.a64.address +
1966 (p->defpdu_data_sz * index);
1967
1968 list_add_tail(&pasync_data_h->link,
1969 &pasync_ctx->async_data.free_list);
1970 pasync_data_h++;
1971 pasync_ctx->async_data.free_entries++;
1972 pasync_ctx->async_data.writables++;
1973
1974 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list);
1975 }
1976
1977 pasync_ctx->async_header.host_write_ptr = 0;
1978 pasync_ctx->async_header.ep_read_ptr = -1;
1979 pasync_ctx->async_data.host_write_ptr = 0;
1980 pasync_ctx->async_data.ep_read_ptr = -1;
1981}
1982
1983static int
1984be_sgl_create_contiguous(void *virtual_address,
1985 u64 physical_address, u32 length,
1986 struct be_dma_mem *sgl)
1987{
1988 WARN_ON(!virtual_address);
1989 WARN_ON(!physical_address);
1990 WARN_ON(!length > 0);
1991 WARN_ON(!sgl);
1992
1993 sgl->va = virtual_address;
1994 sgl->dma = physical_address;
1995 sgl->size = length;
1996
1997 return 0;
1998}
1999
2000static void be_sgl_destroy_contiguous(struct be_dma_mem *sgl)
2001{
2002 memset(sgl, 0, sizeof(*sgl));
2003}
2004
2005static void
2006hwi_build_be_sgl_arr(struct beiscsi_hba *phba,
2007 struct mem_array *pmem, struct be_dma_mem *sgl)
2008{
2009 if (sgl->va)
2010 be_sgl_destroy_contiguous(sgl);
2011
2012 be_sgl_create_contiguous(pmem->virtual_address,
2013 pmem->bus_address.u.a64.address,
2014 pmem->size, sgl);
2015}
2016
2017static void
2018hwi_build_be_sgl_by_offset(struct beiscsi_hba *phba,
2019 struct mem_array *pmem, struct be_dma_mem *sgl)
2020{
2021 if (sgl->va)
2022 be_sgl_destroy_contiguous(sgl);
2023
2024 be_sgl_create_contiguous((unsigned char *)pmem->virtual_address,
2025 pmem->bus_address.u.a64.address,
2026 pmem->size, sgl);
2027}
2028
2029static int be_fill_queue(struct be_queue_info *q,
2030 u16 len, u16 entry_size, void *vaddress)
2031{
2032 struct be_dma_mem *mem = &q->dma_mem;
2033
2034 memset(q, 0, sizeof(*q));
2035 q->len = len;
2036 q->entry_size = entry_size;
2037 mem->size = len * entry_size;
2038 mem->va = vaddress;
2039 if (!mem->va)
2040 return -ENOMEM;
2041 memset(mem->va, 0, mem->size);
2042 return 0;
2043}
2044
2045static int beiscsi_create_eq(struct beiscsi_hba *phba,
2046 struct hwi_context_memory *phwi_context)
2047{
2048 unsigned int idx;
2049 int ret;
2050 struct be_queue_info *eq;
2051 struct be_dma_mem *mem;
2052 struct be_mem_descriptor *mem_descr;
2053 void *eq_vaddress;
2054
2055 idx = 0;
2056 eq = &phwi_context->be_eq.q;
2057 mem = &eq->dma_mem;
2058 mem_descr = phba->init_mem;
2059 mem_descr += HWI_MEM_EQ;
2060 eq_vaddress = mem_descr->mem_array[idx].virtual_address;
2061
2062 ret = be_fill_queue(eq, phba->params.num_eq_entries,
2063 sizeof(struct be_eq_entry), eq_vaddress);
2064 if (ret) {
2065 shost_printk(KERN_ERR, phba->shost,
2066 "be_fill_queue Failed for EQ \n");
2067 return ret;
2068 }
2069
2070 mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
2071
2072 ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
2073 phwi_context->be_eq.cur_eqd);
2074 if (ret) {
2075 shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create"
2076 "Failedfor EQ \n");
2077 return ret;
2078 }
2079 SE_DEBUG(DBG_LVL_8, "eq id is %d\n", phwi_context->be_eq.q.id);
2080 return 0;
2081}
2082
2083static int beiscsi_create_cq(struct beiscsi_hba *phba,
2084 struct hwi_context_memory *phwi_context)
2085{
2086 unsigned int idx;
2087 int ret;
2088 struct be_queue_info *cq, *eq;
2089 struct be_dma_mem *mem;
2090 struct be_mem_descriptor *mem_descr;
2091 void *cq_vaddress;
2092
2093 idx = 0;
2094 cq = &phwi_context->be_cq;
2095 eq = &phwi_context->be_eq.q;
2096 mem = &cq->dma_mem;
2097 mem_descr = phba->init_mem;
2098 mem_descr += HWI_MEM_CQ;
2099 cq_vaddress = mem_descr->mem_array[idx].virtual_address;
2100 ret = be_fill_queue(cq, phba->params.icds_per_ctrl / 2,
2101 sizeof(struct sol_cqe), cq_vaddress);
2102 if (ret) {
2103 shost_printk(KERN_ERR, phba->shost,
2104 "be_fill_queue Failed for ISCSI CQ \n");
2105 return ret;
2106 }
2107
2108 mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
2109 ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0);
2110 if (ret) {
2111 shost_printk(KERN_ERR, phba->shost,
2112 "beiscsi_cmd_eq_create Failed for ISCSI CQ \n");
2113 return ret;
2114 }
2115 SE_DEBUG(DBG_LVL_8, "iscsi cq id is %d\n", phwi_context->be_cq.id);
2116 SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n");
2117 return 0;
2118}
2119
2120static int
2121beiscsi_create_def_hdr(struct beiscsi_hba *phba,
2122 struct hwi_context_memory *phwi_context,
2123 struct hwi_controller *phwi_ctrlr,
2124 unsigned int def_pdu_ring_sz)
2125{
2126 unsigned int idx;
2127 int ret;
2128 struct be_queue_info *dq, *cq;
2129 struct be_dma_mem *mem;
2130 struct be_mem_descriptor *mem_descr;
2131 void *dq_vaddress;
2132
2133 idx = 0;
2134 dq = &phwi_context->be_def_hdrq;
2135 cq = &phwi_context->be_cq;
2136 mem = &dq->dma_mem;
2137 mem_descr = phba->init_mem;
2138 mem_descr += HWI_MEM_ASYNC_HEADER_RING;
2139 dq_vaddress = mem_descr->mem_array[idx].virtual_address;
2140 ret = be_fill_queue(dq, mem_descr->mem_array[0].size /
2141 sizeof(struct phys_addr),
2142 sizeof(struct phys_addr), dq_vaddress);
2143 if (ret) {
2144 shost_printk(KERN_ERR, phba->shost,
2145 "be_fill_queue Failed for DEF PDU HDR\n");
2146 return ret;
2147 }
2148 mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
2149 ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq,
2150 def_pdu_ring_sz,
2151 phba->params.defpdu_hdr_sz);
2152 if (ret) {
2153 shost_printk(KERN_ERR, phba->shost,
2154 "be_cmd_create_default_pdu_queue Failed DEFHDR\n");
2155 return ret;
2156 }
2157 phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id;
2158 SE_DEBUG(DBG_LVL_8, "iscsi def pdu id is %d\n",
2159 phwi_context->be_def_hdrq.id);
2160 hwi_post_async_buffers(phba, 1);
2161 return 0;
2162}
2163
2164static int
2165beiscsi_create_def_data(struct beiscsi_hba *phba,
2166 struct hwi_context_memory *phwi_context,
2167 struct hwi_controller *phwi_ctrlr,
2168 unsigned int def_pdu_ring_sz)
2169{
2170 unsigned int idx;
2171 int ret;
2172 struct be_queue_info *dataq, *cq;
2173 struct be_dma_mem *mem;
2174 struct be_mem_descriptor *mem_descr;
2175 void *dq_vaddress;
2176
2177 idx = 0;
2178 dataq = &phwi_context->be_def_dataq;
2179 cq = &phwi_context->be_cq;
2180 mem = &dataq->dma_mem;
2181 mem_descr = phba->init_mem;
2182 mem_descr += HWI_MEM_ASYNC_DATA_RING;
2183 dq_vaddress = mem_descr->mem_array[idx].virtual_address;
2184 ret = be_fill_queue(dataq, mem_descr->mem_array[0].size /
2185 sizeof(struct phys_addr),
2186 sizeof(struct phys_addr), dq_vaddress);
2187 if (ret) {
2188 shost_printk(KERN_ERR, phba->shost,
2189 "be_fill_queue Failed for DEF PDU DATA\n");
2190 return ret;
2191 }
2192 mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address;
2193 ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq,
2194 def_pdu_ring_sz,
2195 phba->params.defpdu_data_sz);
2196 if (ret) {
2197 shost_printk(KERN_ERR, phba->shost,
2198 "be_cmd_create_default_pdu_queue Failed"
2199 " for DEF PDU DATA\n");
2200 return ret;
2201 }
2202 phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id;
2203 SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n",
2204 phwi_context->be_def_dataq.id);
2205 hwi_post_async_buffers(phba, 0);
2206 SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED \n");
2207 return 0;
2208}
2209
2210static int
2211beiscsi_post_pages(struct beiscsi_hba *phba)
2212{
2213 struct be_mem_descriptor *mem_descr;
2214 struct mem_array *pm_arr;
2215 unsigned int page_offset, i;
2216 struct be_dma_mem sgl;
2217 int status;
2218
2219 mem_descr = phba->init_mem;
2220 mem_descr += HWI_MEM_SGE;
2221 pm_arr = mem_descr->mem_array;
2222
2223 page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io *
2224 phba->fw_config.iscsi_icd_start) / PAGE_SIZE;
2225 for (i = 0; i < mem_descr->num_elements; i++) {
2226 hwi_build_be_sgl_arr(phba, pm_arr, &sgl);
2227 status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl,
2228 page_offset,
2229 (pm_arr->size / PAGE_SIZE));
2230 page_offset += pm_arr->size / PAGE_SIZE;
2231 if (status != 0) {
2232 shost_printk(KERN_ERR, phba->shost,
2233 "post sgl failed.\n");
2234 return status;
2235 }
2236 pm_arr++;
2237 }
2238 SE_DEBUG(DBG_LVL_8, "POSTED PAGES \n");
2239 return 0;
2240}
2241
2242static int
2243beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
2244 struct hwi_context_memory *phwi_context,
2245 struct hwi_controller *phwi_ctrlr)
2246{
2247 unsigned int wrb_mem_index, offset, size, num_wrb_rings;
2248 u64 pa_addr_lo;
2249 unsigned int idx, num, i;
2250 struct mem_array *pwrb_arr;
2251 void *wrb_vaddr;
2252 struct be_dma_mem sgl;
2253 struct be_mem_descriptor *mem_descr;
2254 int status;
2255
2256 idx = 0;
2257 mem_descr = phba->init_mem;
2258 mem_descr += HWI_MEM_WRB;
2259 pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl,
2260 GFP_KERNEL);
2261 if (!pwrb_arr) {
2262 shost_printk(KERN_ERR, phba->shost,
2263 "Memory alloc failed in create wrb ring.\n");
2264 return -ENOMEM;
2265 }
2266 wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
2267 pa_addr_lo = mem_descr->mem_array[idx].bus_address.u.a64.address;
2268 num_wrb_rings = mem_descr->mem_array[idx].size /
2269 (phba->params.wrbs_per_cxn * sizeof(struct iscsi_wrb));
2270
2271 for (num = 0; num < phba->params.cxns_per_ctrl; num++) {
2272 if (num_wrb_rings) {
2273 pwrb_arr[num].virtual_address = wrb_vaddr;
2274 pwrb_arr[num].bus_address.u.a64.address = pa_addr_lo;
2275 pwrb_arr[num].size = phba->params.wrbs_per_cxn *
2276 sizeof(struct iscsi_wrb);
2277 wrb_vaddr += pwrb_arr[num].size;
2278 pa_addr_lo += pwrb_arr[num].size;
2279 num_wrb_rings--;
2280 } else {
2281 idx++;
2282 wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
2283 pa_addr_lo = mem_descr->mem_array[idx].\
2284 bus_address.u.a64.address;
2285 num_wrb_rings = mem_descr->mem_array[idx].size /
2286 (phba->params.wrbs_per_cxn *
2287 sizeof(struct iscsi_wrb));
2288 pwrb_arr[num].virtual_address = wrb_vaddr;
2289 pwrb_arr[num].bus_address.u.a64.address\
2290 = pa_addr_lo;
2291 pwrb_arr[num].size = phba->params.wrbs_per_cxn *
2292 sizeof(struct iscsi_wrb);
2293 wrb_vaddr += pwrb_arr[num].size;
2294 pa_addr_lo += pwrb_arr[num].size;
2295 num_wrb_rings--;
2296 }
2297 }
2298 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
2299 wrb_mem_index = 0;
2300 offset = 0;
2301 size = 0;
2302
2303 hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl);
2304 status = be_cmd_wrbq_create(&phba->ctrl, &sgl,
2305 &phwi_context->be_wrbq[i]);
2306 if (status != 0) {
2307 shost_printk(KERN_ERR, phba->shost,
2308 "wrbq create failed.");
2309 return status;
2310 }
2311 phwi_ctrlr->wrb_context[i].cid = phwi_context->be_wrbq[i].id;
2312 }
2313 kfree(pwrb_arr);
2314 return 0;
2315}
2316
2317static void free_wrb_handles(struct beiscsi_hba *phba)
2318{
2319 unsigned int index;
2320 struct hwi_controller *phwi_ctrlr;
2321 struct hwi_wrb_context *pwrb_context;
2322
2323 phwi_ctrlr = phba->phwi_ctrlr;
2324 for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
2325 pwrb_context = &phwi_ctrlr->wrb_context[index];
2326 kfree(pwrb_context->pwrb_handle_base);
2327 kfree(pwrb_context->pwrb_handle_basestd);
2328 }
2329}
2330
2331static void hwi_cleanup(struct beiscsi_hba *phba)
2332{
2333 struct be_queue_info *q;
2334 struct be_ctrl_info *ctrl = &phba->ctrl;
2335 struct hwi_controller *phwi_ctrlr;
2336 struct hwi_context_memory *phwi_context;
2337 int i;
2338
2339 phwi_ctrlr = phba->phwi_ctrlr;
2340 phwi_context = phwi_ctrlr->phwi_ctxt;
2341 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
2342 q = &phwi_context->be_wrbq[i];
2343 if (q->created)
2344 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
2345 }
2346
2347 free_wrb_handles(phba);
2348
2349 q = &phwi_context->be_def_hdrq;
2350 if (q->created)
2351 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
2352
2353 q = &phwi_context->be_def_dataq;
2354 if (q->created)
2355 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
2356
2357 beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
2358
2359 q = &phwi_context->be_cq;
2360 if (q->created)
2361 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
2362
2363 q = &phwi_context->be_eq.q;
2364 if (q->created)
2365 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
2366}
2367
2368static int hwi_init_port(struct beiscsi_hba *phba)
2369{
2370 struct hwi_controller *phwi_ctrlr;
2371 struct hwi_context_memory *phwi_context;
2372 unsigned int def_pdu_ring_sz;
2373 struct be_ctrl_info *ctrl = &phba->ctrl;
2374 int status;
2375
2376 def_pdu_ring_sz =
2377 phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr);
2378 phwi_ctrlr = phba->phwi_ctrlr;
2379
2380 phwi_context = phwi_ctrlr->phwi_ctxt;
2381 phwi_context->be_eq.max_eqd = 0;
2382 phwi_context->be_eq.min_eqd = 0;
2383 phwi_context->be_eq.cur_eqd = 64;
2384 phwi_context->be_eq.enable_aic = false;
2385 be_cmd_fw_initialize(&phba->ctrl);
2386 status = beiscsi_create_eq(phba, phwi_context);
2387 if (status != 0) {
2388 shost_printk(KERN_ERR, phba->shost, "EQ not created \n");
2389 goto error;
2390 }
2391
2392 status = mgmt_check_supported_fw(ctrl);
2393 if (status != 0) {
2394 shost_printk(KERN_ERR, phba->shost,
2395 "Unsupported fw version \n");
2396 goto error;
2397 }
2398
2399 status = mgmt_get_fw_config(ctrl, phba);
2400 if (status != 0) {
2401 shost_printk(KERN_ERR, phba->shost,
2402 "Error getting fw config\n");
2403 goto error;
2404 }
2405
2406 status = beiscsi_create_cq(phba, phwi_context);
2407 if (status != 0) {
2408 shost_printk(KERN_ERR, phba->shost, "CQ not created\n");
2409 goto error;
2410 }
2411
2412 status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr,
2413 def_pdu_ring_sz);
2414 if (status != 0) {
2415 shost_printk(KERN_ERR, phba->shost,
2416 "Default Header not created\n");
2417 goto error;
2418 }
2419
2420 status = beiscsi_create_def_data(phba, phwi_context,
2421 phwi_ctrlr, def_pdu_ring_sz);
2422 if (status != 0) {
2423 shost_printk(KERN_ERR, phba->shost,
2424 "Default Data not created\n");
2425 goto error;
2426 }
2427
2428 status = beiscsi_post_pages(phba);
2429 if (status != 0) {
2430 shost_printk(KERN_ERR, phba->shost, "Post SGL Pages Failed\n");
2431 goto error;
2432 }
2433
2434 status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr);
2435 if (status != 0) {
2436 shost_printk(KERN_ERR, phba->shost,
2437 "WRB Rings not created\n");
2438 goto error;
2439 }
2440
2441 SE_DEBUG(DBG_LVL_8, "hwi_init_port success\n");
2442 return 0;
2443
2444error:
2445 shost_printk(KERN_ERR, phba->shost, "hwi_init_port failed");
2446 hwi_cleanup(phba);
2447 return -ENOMEM;
2448}
2449
2450
2451static int hwi_init_controller(struct beiscsi_hba *phba)
2452{
2453 struct hwi_controller *phwi_ctrlr;
2454
2455 phwi_ctrlr = phba->phwi_ctrlr;
2456 if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) {
2457 phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba->
2458 init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address;
2459 SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p \n",
2460 phwi_ctrlr->phwi_ctxt);
2461 } else {
2462 shost_printk(KERN_ERR, phba->shost,
2463 "HWI_MEM_ADDN_CONTEXT is more than one element."
2464 "Failing to load\n");
2465 return -ENOMEM;
2466 }
2467
2468 iscsi_init_global_templates(phba);
2469 beiscsi_init_wrb_handle(phba);
2470 hwi_init_async_pdu_ctx(phba);
2471 if (hwi_init_port(phba) != 0) {
2472 shost_printk(KERN_ERR, phba->shost,
2473 "hwi_init_controller failed\n");
2474 return -ENOMEM;
2475 }
2476 return 0;
2477}
2478
2479static void beiscsi_free_mem(struct beiscsi_hba *phba)
2480{
2481 struct be_mem_descriptor *mem_descr;
2482 int i, j;
2483
2484 mem_descr = phba->init_mem;
2485 i = 0;
2486 j = 0;
2487 for (i = 0; i < SE_MEM_MAX; i++) {
2488 for (j = mem_descr->num_elements; j > 0; j--) {
2489 pci_free_consistent(phba->pcidev,
2490 mem_descr->mem_array[j - 1].size,
2491 mem_descr->mem_array[j - 1].virtual_address,
2492 mem_descr->mem_array[j - 1].bus_address.
2493 u.a64.address);
2494 }
2495 kfree(mem_descr->mem_array);
2496 mem_descr++;
2497 }
2498 kfree(phba->init_mem);
2499 kfree(phba->phwi_ctrlr);
2500}
2501
2502static int beiscsi_init_controller(struct beiscsi_hba *phba)
2503{
2504 int ret = -ENOMEM;
2505
2506 ret = beiscsi_get_memory(phba);
2507 if (ret < 0) {
2508 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -"
2509 "Failed in beiscsi_alloc_memory \n");
2510 return ret;
2511 }
2512
2513 ret = hwi_init_controller(phba);
2514 if (ret)
2515 goto free_init;
2516 SE_DEBUG(DBG_LVL_8, "Return success from beiscsi_init_controller");
2517 return 0;
2518
2519free_init:
2520 beiscsi_free_mem(phba);
2521 return -ENOMEM;
2522}
2523
2524static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
2525{
2526 struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg;
2527 struct sgl_handle *psgl_handle;
2528 struct iscsi_sge *pfrag;
2529 unsigned int arr_index, i, idx;
2530
2531 phba->io_sgl_hndl_avbl = 0;
2532 phba->eh_sgl_hndl_avbl = 0;
2533 mem_descr_sglh = phba->init_mem;
2534 mem_descr_sglh += HWI_MEM_SGLH;
2535 if (1 == mem_descr_sglh->num_elements) {
2536 phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
2537 phba->params.ios_per_ctrl,
2538 GFP_KERNEL);
2539 if (!phba->io_sgl_hndl_base) {
2540 shost_printk(KERN_ERR, phba->shost,
2541 "Mem Alloc Failed. Failing to load\n");
2542 return -ENOMEM;
2543 }
2544 phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
2545 (phba->params.icds_per_ctrl -
2546 phba->params.ios_per_ctrl),
2547 GFP_KERNEL);
2548 if (!phba->eh_sgl_hndl_base) {
2549 kfree(phba->io_sgl_hndl_base);
2550 shost_printk(KERN_ERR, phba->shost,
2551 "Mem Alloc Failed. Failing to load\n");
2552 return -ENOMEM;
2553 }
2554 } else {
2555 shost_printk(KERN_ERR, phba->shost,
2556 "HWI_MEM_SGLH is more than one element."
2557 "Failing to load\n");
2558 return -ENOMEM;
2559 }
2560
2561 arr_index = 0;
2562 idx = 0;
2563 while (idx < mem_descr_sglh->num_elements) {
2564 psgl_handle = mem_descr_sglh->mem_array[idx].virtual_address;
2565
2566 for (i = 0; i < (mem_descr_sglh->mem_array[idx].size /
2567 sizeof(struct sgl_handle)); i++) {
2568 if (arr_index < phba->params.ios_per_ctrl) {
2569 phba->io_sgl_hndl_base[arr_index] = psgl_handle;
2570 phba->io_sgl_hndl_avbl++;
2571 arr_index++;
2572 } else {
2573 phba->eh_sgl_hndl_base[arr_index -
2574 phba->params.ios_per_ctrl] =
2575 psgl_handle;
2576 arr_index++;
2577 phba->eh_sgl_hndl_avbl++;
2578 }
2579 psgl_handle++;
2580 }
2581 idx++;
2582 }
2583 SE_DEBUG(DBG_LVL_8,
2584 "phba->io_sgl_hndl_avbl=%d"
2585 "phba->eh_sgl_hndl_avbl=%d \n",
2586 phba->io_sgl_hndl_avbl,
2587 phba->eh_sgl_hndl_avbl);
2588 mem_descr_sg = phba->init_mem;
2589 mem_descr_sg += HWI_MEM_SGE;
2590 SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d \n",
2591 mem_descr_sg->num_elements);
2592 arr_index = 0;
2593 idx = 0;
2594 while (idx < mem_descr_sg->num_elements) {
2595 pfrag = mem_descr_sg->mem_array[idx].virtual_address;
2596
2597 for (i = 0;
2598 i < (mem_descr_sg->mem_array[idx].size) /
2599 (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io);
2600 i++) {
2601 if (arr_index < phba->params.ios_per_ctrl)
2602 psgl_handle = phba->io_sgl_hndl_base[arr_index];
2603 else
2604 psgl_handle = phba->eh_sgl_hndl_base[arr_index -
2605 phba->params.ios_per_ctrl];
2606 psgl_handle->pfrag = pfrag;
2607 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0);
2608 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0);
2609 pfrag += phba->params.num_sge_per_io;
2610 psgl_handle->sgl_index =
2611 phba->fw_config.iscsi_cid_start + arr_index++;
2612 }
2613 idx++;
2614 }
2615 phba->io_sgl_free_index = 0;
2616 phba->io_sgl_alloc_index = 0;
2617 phba->eh_sgl_free_index = 0;
2618 phba->eh_sgl_alloc_index = 0;
2619 return 0;
2620}
2621
2622static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
2623{
2624 int i, new_cid;
2625
2626 phba->cid_array = kmalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
2627 GFP_KERNEL);
2628 if (!phba->cid_array) {
2629 shost_printk(KERN_ERR, phba->shost,
2630 "Failed to allocate memory in "
2631 "hba_setup_cid_tbls\n");
2632 return -ENOMEM;
2633 }
2634 phba->ep_array = kmalloc(sizeof(struct iscsi_endpoint *) *
2635 phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
2636 if (!phba->ep_array) {
2637 shost_printk(KERN_ERR, phba->shost,
2638 "Failed to allocate memory in "
2639 "hba_setup_cid_tbls \n");
2640 kfree(phba->cid_array);
2641 return -ENOMEM;
2642 }
2643 new_cid = phba->fw_config.iscsi_icd_start;
2644 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
2645 phba->cid_array[i] = new_cid;
2646 new_cid += 2;
2647 }
2648 phba->avlbl_cids = phba->params.cxns_per_ctrl;
2649 return 0;
2650}
2651
2652static unsigned char hwi_enable_intr(struct beiscsi_hba *phba)
2653{
2654 struct be_ctrl_info *ctrl = &phba->ctrl;
2655 struct hwi_controller *phwi_ctrlr;
2656 struct hwi_context_memory *phwi_context;
2657 struct be_queue_info *eq;
2658 u8 __iomem *addr;
2659 u32 reg;
2660 u32 enabled;
2661
2662 phwi_ctrlr = phba->phwi_ctrlr;
2663 phwi_context = phwi_ctrlr->phwi_ctxt;
2664
2665 eq = &phwi_context->be_eq.q;
2666 addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
2667 PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
2668 reg = ioread32(addr);
2669 SE_DEBUG(DBG_LVL_8, "reg =x%08x \n", reg);
2670
2671 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
2672 if (!enabled) {
2673 reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
2674 SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr);
2675 iowrite32(reg, addr);
2676 SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id);
2677
2678 hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
2679 } else
2680 shost_printk(KERN_WARNING, phba->shost,
2681 "In hwi_enable_intr, Not Enabled \n");
2682 return true;
2683}
2684
2685static void hwi_disable_intr(struct beiscsi_hba *phba)
2686{
2687 struct be_ctrl_info *ctrl = &phba->ctrl;
2688
2689 u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
2690 u32 reg = ioread32(addr);
2691
2692 u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
2693 if (enabled) {
2694 reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
2695 iowrite32(reg, addr);
2696 } else
2697 shost_printk(KERN_WARNING, phba->shost,
2698 "In hwi_disable_intr, Already Disabled \n");
2699}
2700
2701static int beiscsi_init_port(struct beiscsi_hba *phba)
2702{
2703 int ret;
2704
2705 ret = beiscsi_init_controller(phba);
2706 if (ret < 0) {
2707 shost_printk(KERN_ERR, phba->shost,
2708 "beiscsi_dev_probe - Failed in"
2709 "beiscsi_init_controller \n");
2710 return ret;
2711 }
2712 ret = beiscsi_init_sgl_handle(phba);
2713 if (ret < 0) {
2714 shost_printk(KERN_ERR, phba->shost,
2715 "beiscsi_dev_probe - Failed in"
2716 "beiscsi_init_sgl_handle \n");
2717 goto do_cleanup_ctrlr;
2718 }
2719
2720 if (hba_setup_cid_tbls(phba)) {
2721 shost_printk(KERN_ERR, phba->shost,
2722 "Failed in hba_setup_cid_tbls\n");
2723 kfree(phba->io_sgl_hndl_base);
2724 kfree(phba->eh_sgl_hndl_base);
2725 goto do_cleanup_ctrlr;
2726 }
2727
2728 return ret;
2729
2730do_cleanup_ctrlr:
2731 hwi_cleanup(phba);
2732 return ret;
2733}
2734
2735static void hwi_purge_eq(struct beiscsi_hba *phba)
2736{
2737 struct hwi_controller *phwi_ctrlr;
2738 struct hwi_context_memory *phwi_context;
2739 struct be_queue_info *eq;
2740 struct be_eq_entry *eqe = NULL;
2741
2742 phwi_ctrlr = phba->phwi_ctrlr;
2743 phwi_context = phwi_ctrlr->phwi_ctxt;
2744 eq = &phwi_context->be_eq.q;
2745 eqe = queue_tail_node(eq);
2746
2747 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
2748 & EQE_VALID_MASK) {
2749 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
2750 queue_tail_inc(eq);
2751 eqe = queue_tail_node(eq);
2752 }
2753}
2754
2755static void beiscsi_clean_port(struct beiscsi_hba *phba)
2756{
2757 unsigned char mgmt_status;
2758
2759 mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0);
2760 if (mgmt_status)
2761 shost_printk(KERN_WARNING, phba->shost,
2762 "mgmt_epfw_cleanup FAILED \n");
2763 hwi_cleanup(phba);
2764 hwi_purge_eq(phba);
2765 kfree(phba->io_sgl_hndl_base);
2766 kfree(phba->eh_sgl_hndl_base);
2767 kfree(phba->cid_array);
2768 kfree(phba->ep_array);
2769}
2770
2771void
2772beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
2773 struct beiscsi_offload_params *params)
2774{
2775 struct wrb_handle *pwrb_handle;
2776 struct iscsi_target_context_update_wrb *pwrb = NULL;
2777 struct be_mem_descriptor *mem_descr;
2778 struct beiscsi_hba *phba = beiscsi_conn->phba;
2779 u32 doorbell = 0;
2780
2781 /*
2782 * We can always use 0 here because it is reserved by libiscsi for
2783 * login/startup related tasks.
2784 */
2785 pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid, 0);
2786 pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
2787 memset(pwrb, 0, sizeof(*pwrb));
2788 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2789 max_burst_length, pwrb, params->dw[offsetof
2790 (struct amap_beiscsi_offload_params,
2791 max_burst_length) / 32]);
2792 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2793 max_send_data_segment_length, pwrb,
2794 params->dw[offsetof(struct amap_beiscsi_offload_params,
2795 max_send_data_segment_length) / 32]);
2796 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2797 first_burst_length,
2798 pwrb,
2799 params->dw[offsetof(struct amap_beiscsi_offload_params,
2800 first_burst_length) / 32]);
2801
2802 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
2803 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2804 erl) / 32] & OFFLD_PARAMS_ERL));
2805 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
2806 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2807 dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
2808 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
2809 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2810 hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
2811 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
2812 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2813 ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
2814 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
2815 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2816 imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
2817 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
2818 pwrb,
2819 (params->dw[offsetof(struct amap_beiscsi_offload_params,
2820 exp_statsn) / 32] + 1));
2821 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
2822 0x7);
2823 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
2824 pwrb, pwrb_handle->wrb_index);
2825 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
2826 pwrb, pwrb_handle->nxt_wrb_index);
2827 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2828 session_state, pwrb, 0);
2829 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
2830 pwrb, 1);
2831 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
2832 pwrb, 0);
2833 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
2834 0);
2835
2836 mem_descr = phba->init_mem;
2837 mem_descr += ISCSI_MEM_GLOBAL_HEADER;
2838
2839 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2840 pad_buffer_addr_hi, pwrb,
2841 mem_descr->mem_array[0].bus_address.u.a32.address_hi);
2842 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
2843 pad_buffer_addr_lo, pwrb,
2844 mem_descr->mem_array[0].bus_address.u.a32.address_lo);
2845
2846 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
2847
2848 doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
2849 doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) <<
2850 DB_DEF_PDU_WRB_INDEX_SHIFT;
2851 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
2852
2853 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
2854}
2855
2856static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
2857 int *index, int *age)
2858{
2859 *index = be32_to_cpu(itt) >> 16;
2860 if (age)
2861 *age = conn->session->age;
2862}
2863
2864/**
2865 * beiscsi_alloc_pdu - allocates pdu and related resources
2866 * @task: libiscsi task
2867 * @opcode: opcode of pdu for task
2868 *
2869 * This is called with the session lock held. It will allocate
2870 * the wrb and sgl if needed for the command. And it will prep
2871 * the pdu's itt. beiscsi_parse_pdu will later translate
2872 * the pdu itt to the libiscsi task itt.
2873 */
2874static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
2875{
2876 struct beiscsi_io_task *io_task = task->dd_data;
2877 struct iscsi_conn *conn = task->conn;
2878 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
2879 struct beiscsi_hba *phba = beiscsi_conn->phba;
2880 struct hwi_wrb_context *pwrb_context;
2881 struct hwi_controller *phwi_ctrlr;
2882 itt_t itt;
2883
2884 io_task->pwrb_handle = alloc_wrb_handle(phba,
2885 beiscsi_conn->beiscsi_conn_cid,
2886 task->itt);
2887 io_task->pwrb_handle->pio_handle = task;
2888 io_task->conn = beiscsi_conn;
2889
2890 task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
2891 task->hdr_max = sizeof(struct be_cmd_bhs);
2892
2893 if (task->sc) {
2894 spin_lock(&phba->io_sgl_lock);
2895 io_task->psgl_handle = alloc_io_sgl_handle(phba);
2896 spin_unlock(&phba->io_sgl_lock);
2897 if (!io_task->psgl_handle) {
2898 phwi_ctrlr = phba->phwi_ctrlr;
2899 pwrb_context = &phwi_ctrlr->wrb_context
2900 [beiscsi_conn->beiscsi_conn_cid];
2901 free_wrb_handle(phba, pwrb_context,
2902 io_task->pwrb_handle);
2903 io_task->pwrb_handle = NULL;
2904 SE_DEBUG(DBG_LVL_1,
2905 "Alloc of SGL_ICD Failed \n");
2906 return -ENOMEM;
2907 }
2908 } else {
2909 io_task->scsi_cmnd = NULL;
2910 if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
2911 if (!beiscsi_conn->login_in_progress) {
2912 spin_lock(&phba->mgmt_sgl_lock);
2913 io_task->psgl_handle = (struct sgl_handle *)
2914 alloc_mgmt_sgl_handle(phba);
2915 spin_unlock(&phba->mgmt_sgl_lock);
2916 if (!io_task->psgl_handle) {
2917 phwi_ctrlr = phba->phwi_ctrlr;
2918 pwrb_context =
2919 &phwi_ctrlr->wrb_context
2920 [beiscsi_conn->beiscsi_conn_cid];
2921 free_wrb_handle(phba, pwrb_context,
2922 io_task->pwrb_handle);
2923 io_task->pwrb_handle = NULL;
2924 SE_DEBUG(DBG_LVL_1, "Alloc of "
2925 "MGMT_SGL_ICD Failed \n");
2926 return -ENOMEM;
2927 }
2928 beiscsi_conn->login_in_progress = 1;
2929 beiscsi_conn->plogin_sgl_handle =
2930 io_task->psgl_handle;
2931 } else {
2932 io_task->psgl_handle =
2933 beiscsi_conn->plogin_sgl_handle;
2934 }
2935 } else {
2936 spin_lock(&phba->mgmt_sgl_lock);
2937 io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
2938 spin_unlock(&phba->mgmt_sgl_lock);
2939 if (!io_task->psgl_handle) {
2940 phwi_ctrlr = phba->phwi_ctrlr;
2941 pwrb_context = &phwi_ctrlr->wrb_context
2942 [beiscsi_conn->beiscsi_conn_cid];
2943 free_wrb_handle(phba, pwrb_context,
2944 io_task->pwrb_handle);
2945 io_task->pwrb_handle = NULL;
2946 SE_DEBUG(DBG_LVL_1, "Alloc of "
2947 "MGMT_SGL_ICD Failed \n");
2948 return -ENOMEM;
2949 }
2950 }
2951 }
2952 itt = (itt_t) cpu_to_be32(((unsigned int)task->itt << 16) |
2953 (unsigned int)(io_task->psgl_handle->sgl_index));
2954 io_task->cmd_bhs->iscsi_hdr.itt = itt;
2955 return 0;
2956}
2957
2958static void beiscsi_cleanup_task(struct iscsi_task *task)
2959{
2960 struct beiscsi_io_task *io_task = task->dd_data;
2961 struct iscsi_conn *conn = task->conn;
2962 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
2963 struct beiscsi_hba *phba = beiscsi_conn->phba;
2964 struct hwi_wrb_context *pwrb_context;
2965 struct hwi_controller *phwi_ctrlr;
2966
2967 phwi_ctrlr = phba->phwi_ctrlr;
2968 pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid];
2969 if (io_task->pwrb_handle) {
2970 free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
2971 io_task->pwrb_handle = NULL;
2972 }
2973
2974 if (task->sc) {
2975 if (io_task->psgl_handle) {
2976 spin_lock(&phba->io_sgl_lock);
2977 free_io_sgl_handle(phba, io_task->psgl_handle);
2978 spin_unlock(&phba->io_sgl_lock);
2979 io_task->psgl_handle = NULL;
2980 }
2981 } else {
2982 if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)
2983 return;
2984 if (io_task->psgl_handle) {
2985 spin_lock(&phba->mgmt_sgl_lock);
2986 free_mgmt_sgl_handle(phba, io_task->psgl_handle);
2987 spin_unlock(&phba->mgmt_sgl_lock);
2988 io_task->psgl_handle = NULL;
2989 }
2990 }
2991}
2992
2993static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
2994 unsigned int num_sg, unsigned int xferlen,
2995 unsigned int writedir)
2996{
2997
2998 struct beiscsi_io_task *io_task = task->dd_data;
2999 struct iscsi_conn *conn = task->conn;
3000 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
3001 struct beiscsi_hba *phba = beiscsi_conn->phba;
3002 struct iscsi_wrb *pwrb = NULL;
3003 unsigned int doorbell = 0;
3004
3005 pwrb = io_task->pwrb_handle->pwrb;
3006
3007 io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
3008 io_task->bhs_len = sizeof(struct be_cmd_bhs);
3009
3010 if (writedir) {
3011 SE_DEBUG(DBG_LVL_4, " WRITE Command \t");
3012 memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48);
3013 AMAP_SET_BITS(struct amap_pdu_data_out, itt,
3014 &io_task->cmd_bhs->iscsi_data_pdu,
3015 (unsigned int)io_task->cmd_bhs->iscsi_hdr.itt);
3016 AMAP_SET_BITS(struct amap_pdu_data_out, opcode,
3017 &io_task->cmd_bhs->iscsi_data_pdu,
3018 ISCSI_OPCODE_SCSI_DATA_OUT);
3019 AMAP_SET_BITS(struct amap_pdu_data_out, final_bit,
3020 &io_task->cmd_bhs->iscsi_data_pdu, 1);
3021 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
3022 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
3023
3024 } else {
3025 SE_DEBUG(DBG_LVL_4, "READ Command \t");
3026 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD);
3027 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
3028 }
3029 memcpy(&io_task->cmd_bhs->iscsi_data_pdu.
3030 dw[offsetof(struct amap_pdu_data_out, lun) / 32],
3031 io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun));
3032
3033 AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
3034 cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr.
3035 lun[0]));
3036 AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
3037 AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
3038 io_task->pwrb_handle->wrb_index);
3039 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
3040 be32_to_cpu(task->cmdsn));
3041 AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
3042 io_task->psgl_handle->sgl_index);
3043
3044 hwi_write_sgl(pwrb, sg, num_sg, io_task);
3045
3046 AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
3047 io_task->pwrb_handle->nxt_wrb_index);
3048 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
3049
3050 doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
3051 doorbell |= (io_task->pwrb_handle->wrb_index &
3052 DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
3053 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
3054
3055 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
3056 return 0;
3057}
3058
3059static int beiscsi_mtask(struct iscsi_task *task)
3060{
3061 struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data;
3062 struct iscsi_conn *conn = task->conn;
3063 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
3064 struct beiscsi_hba *phba = beiscsi_conn->phba;
3065 struct iscsi_wrb *pwrb = NULL;
3066 unsigned int doorbell = 0;
3067 struct iscsi_task *aborted_task;
3068
3069 pwrb = io_task->pwrb_handle->pwrb;
3070 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
3071 be32_to_cpu(task->cmdsn));
3072 AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
3073 io_task->pwrb_handle->wrb_index);
3074 AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
3075 io_task->psgl_handle->sgl_index);
3076
3077 switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
3078 case ISCSI_OP_LOGIN:
3079 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, TGT_DM_CMD);
3080 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
3081 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
3082 hwi_write_buffer(pwrb, task);
3083 break;
3084 case ISCSI_OP_NOOP_OUT:
3085 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD);
3086 hwi_write_buffer(pwrb, task);
3087 break;
3088 case ISCSI_OP_TEXT:
3089 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD);
3090 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
3091 hwi_write_buffer(pwrb, task);
3092 break;
3093 case ISCSI_OP_SCSI_TMFUNC:
3094 aborted_task = iscsi_itt_to_task(conn,
3095 ((struct iscsi_tm *)task->hdr)->rtt);
3096 if (!aborted_task)
3097 return 0;
3098 aborted_io_task = aborted_task->dd_data;
3099 if (!aborted_io_task->scsi_cmnd)
3100 return 0;
3101
3102 mgmt_invalidate_icds(phba,
3103 aborted_io_task->psgl_handle->sgl_index,
3104 beiscsi_conn->beiscsi_conn_cid);
3105 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD);
3106 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
3107 hwi_write_buffer(pwrb, task);
3108 break;
3109 case ISCSI_OP_LOGOUT:
3110 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
3111 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
3112 HWH_TYPE_LOGOUT);
3113 hwi_write_buffer(pwrb, task);
3114 break;
3115
3116 default:
3117 SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported \n",
3118 task->hdr->opcode & ISCSI_OPCODE_MASK);
3119 return -EINVAL;
3120 }
3121
3122 AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
3123 be32_to_cpu(task->data_count));
3124 AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
3125 io_task->pwrb_handle->nxt_wrb_index);
3126 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
3127
3128 doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
3129 doorbell |= (io_task->pwrb_handle->wrb_index &
3130 DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
3131 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
3132 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
3133 return 0;
3134}
3135
3136static int beiscsi_task_xmit(struct iscsi_task *task)
3137{
3138 struct iscsi_conn *conn = task->conn;
3139 struct beiscsi_io_task *io_task = task->dd_data;
3140 struct scsi_cmnd *sc = task->sc;
3141 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
3142 struct scatterlist *sg;
3143 int num_sg;
3144 unsigned int writedir = 0, xferlen = 0;
3145
3146 SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t"
3147 "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid,
3148 task, conn, beiscsi_conn);
3149 if (!sc)
3150 return beiscsi_mtask(task);
3151
3152 io_task->scsi_cmnd = sc;
3153 num_sg = scsi_dma_map(sc);
3154 if (num_sg < 0) {
3155 SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n")
3156 return num_sg;
3157 }
3158 SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n",
3159 (scsi_bufflen(sc)), sc, num_sg, sc->serial_number);
3160 xferlen = scsi_bufflen(sc);
3161 sg = scsi_sglist(sc);
3162 if (sc->sc_data_direction == DMA_TO_DEVICE) {
3163 writedir = 1;
3164 SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x \n",
3165 task->imm_count);
3166 } else
3167 writedir = 0;
3168 return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
3169}
3170
3171static void beiscsi_remove(struct pci_dev *pcidev)
3172{
3173 struct beiscsi_hba *phba = NULL;
3174
3175 phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
3176 if (!phba) {
3177 dev_err(&pcidev->dev, "beiscsi_remove called with no phba \n");
3178 return;
3179 }
3180
3181 hwi_disable_intr(phba);
3182 if (phba->pcidev->irq)
3183 free_irq(phba->pcidev->irq, phba);
3184 destroy_workqueue(phba->wq);
3185 if (blk_iopoll_enabled)
3186 blk_iopoll_disable(&phba->iopoll);
3187
3188 beiscsi_clean_port(phba);
3189 beiscsi_free_mem(phba);
3190 beiscsi_unmap_pci_function(phba);
3191 pci_free_consistent(phba->pcidev,
3192 phba->ctrl.mbox_mem_alloced.size,
3193 phba->ctrl.mbox_mem_alloced.va,
3194 phba->ctrl.mbox_mem_alloced.dma);
3195 iscsi_host_remove(phba->shost);
3196 pci_dev_put(phba->pcidev);
3197 iscsi_host_free(phba->shost);
3198}
3199
3200static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
3201 const struct pci_device_id *id)
3202{
3203 struct beiscsi_hba *phba = NULL;
3204 int ret;
3205
3206 ret = beiscsi_enable_pci(pcidev);
3207 if (ret < 0) {
3208 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3209 "Failed to enable pci device \n");
3210 return ret;
3211 }
3212
3213 phba = beiscsi_hba_alloc(pcidev);
3214 if (!phba) {
3215 dev_err(&pcidev->dev, "beiscsi_dev_probe-"
3216 " Failed in beiscsi_hba_alloc \n");
3217 goto disable_pci;
3218 }
3219
3220 pci_set_drvdata(pcidev, phba);
3221 ret = be_ctrl_init(phba, pcidev);
3222 if (ret) {
3223 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3224 "Failed in be_ctrl_init\n");
3225 goto hba_free;
3226 }
3227
3228 spin_lock_init(&phba->io_sgl_lock);
3229 spin_lock_init(&phba->mgmt_sgl_lock);
3230 spin_lock_init(&phba->isr_lock);
3231 beiscsi_get_params(phba);
3232 ret = beiscsi_init_port(phba);
3233 if (ret < 0) {
3234 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3235 "Failed in beiscsi_init_port\n");
3236 goto free_port;
3237 }
3238
3239 snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
3240 phba->shost->host_no);
3241 phba->wq = create_singlethread_workqueue(phba->wq_name);
3242 if (!phba->wq) {
3243 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3244 "Failed to allocate work queue\n");
3245 goto free_twq;
3246 }
3247
3248 INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
3249
3250 if (blk_iopoll_enabled) {
3251 blk_iopoll_init(&phba->iopoll, be_iopoll_budget, be_iopoll);
3252 blk_iopoll_enable(&phba->iopoll);
3253 }
3254
3255 ret = beiscsi_init_irqs(phba);
3256 if (ret < 0) {
3257 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3258 "Failed to beiscsi_init_irqs\n");
3259 goto free_blkenbld;
3260 }
3261 ret = hwi_enable_intr(phba);
3262 if (ret < 0) {
3263 shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
3264 "Failed to hwi_enable_intr\n");
3265 goto free_ctrlr;
3266 }
3267
3268 SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n");
3269 return 0;
3270
3271free_ctrlr:
3272 if (phba->pcidev->irq)
3273 free_irq(phba->pcidev->irq, phba);
3274free_blkenbld:
3275 destroy_workqueue(phba->wq);
3276 if (blk_iopoll_enabled)
3277 blk_iopoll_disable(&phba->iopoll);
3278free_twq:
3279 beiscsi_clean_port(phba);
3280 beiscsi_free_mem(phba);
3281free_port:
3282 pci_free_consistent(phba->pcidev,
3283 phba->ctrl.mbox_mem_alloced.size,
3284 phba->ctrl.mbox_mem_alloced.va,
3285 phba->ctrl.mbox_mem_alloced.dma);
3286 beiscsi_unmap_pci_function(phba);
3287hba_free:
3288 iscsi_host_remove(phba->shost);
3289 pci_dev_put(phba->pcidev);
3290 iscsi_host_free(phba->shost);
3291disable_pci:
3292 pci_disable_device(pcidev);
3293 return ret;
3294}
3295
3296struct iscsi_transport beiscsi_iscsi_transport = {
3297 .owner = THIS_MODULE,
3298 .name = DRV_NAME,
3299 .caps = CAP_RECOVERY_L0 | CAP_HDRDGST |
3300 CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
3301 .param_mask = ISCSI_MAX_RECV_DLENGTH |
3302 ISCSI_MAX_XMIT_DLENGTH |
3303 ISCSI_HDRDGST_EN |
3304 ISCSI_DATADGST_EN |
3305 ISCSI_INITIAL_R2T_EN |
3306 ISCSI_MAX_R2T |
3307 ISCSI_IMM_DATA_EN |
3308 ISCSI_FIRST_BURST |
3309 ISCSI_MAX_BURST |
3310 ISCSI_PDU_INORDER_EN |
3311 ISCSI_DATASEQ_INORDER_EN |
3312 ISCSI_ERL |
3313 ISCSI_CONN_PORT |
3314 ISCSI_CONN_ADDRESS |
3315 ISCSI_EXP_STATSN |
3316 ISCSI_PERSISTENT_PORT |
3317 ISCSI_PERSISTENT_ADDRESS |
3318 ISCSI_TARGET_NAME | ISCSI_TPGT |
3319 ISCSI_USERNAME | ISCSI_PASSWORD |
3320 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
3321 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
3322 ISCSI_LU_RESET_TMO |
3323 ISCSI_PING_TMO | ISCSI_RECV_TMO |
3324 ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
3325 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
3326 ISCSI_HOST_INITIATOR_NAME,
3327 .create_session = beiscsi_session_create,
3328 .destroy_session = beiscsi_session_destroy,
3329 .create_conn = beiscsi_conn_create,
3330 .bind_conn = beiscsi_conn_bind,
3331 .destroy_conn = iscsi_conn_teardown,
3332 .set_param = beiscsi_set_param,
3333 .get_conn_param = beiscsi_conn_get_param,
3334 .get_session_param = iscsi_session_get_param,
3335 .get_host_param = beiscsi_get_host_param,
3336 .start_conn = beiscsi_conn_start,
3337 .stop_conn = beiscsi_conn_stop,
3338 .send_pdu = iscsi_conn_send_pdu,
3339 .xmit_task = beiscsi_task_xmit,
3340 .cleanup_task = beiscsi_cleanup_task,
3341 .alloc_pdu = beiscsi_alloc_pdu,
3342 .parse_pdu_itt = beiscsi_parse_pdu,
3343 .get_stats = beiscsi_conn_get_stats,
3344 .ep_connect = beiscsi_ep_connect,
3345 .ep_poll = beiscsi_ep_poll,
3346 .ep_disconnect = beiscsi_ep_disconnect,
3347 .session_recovery_timedout = iscsi_session_recovery_timedout,
3348};
3349
3350static struct pci_driver beiscsi_pci_driver = {
3351 .name = DRV_NAME,
3352 .probe = beiscsi_dev_probe,
3353 .remove = beiscsi_remove,
3354 .id_table = beiscsi_pci_id_table
3355};
3356
3357static int __init beiscsi_module_init(void)
3358{
3359 int ret;
3360
3361 beiscsi_scsi_transport =
3362 iscsi_register_transport(&beiscsi_iscsi_transport);
3363 if (!beiscsi_scsi_transport) {
3364 SE_DEBUG(DBG_LVL_1,
3365 "beiscsi_module_init - Unable to register beiscsi"
3366 "transport.\n");
3367 ret = -ENOMEM;
3368 }
3369 SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n",
3370 &beiscsi_iscsi_transport);
3371
3372 ret = pci_register_driver(&beiscsi_pci_driver);
3373 if (ret) {
3374 SE_DEBUG(DBG_LVL_1,
3375 "beiscsi_module_init - Unable to register"
3376 "beiscsi pci driver.\n");
3377 goto unregister_iscsi_transport;
3378 }
3379 return 0;
3380
3381unregister_iscsi_transport:
3382 iscsi_unregister_transport(&beiscsi_iscsi_transport);
3383 return ret;
3384}
3385
3386static void __exit beiscsi_module_exit(void)
3387{
3388 pci_unregister_driver(&beiscsi_pci_driver);
3389 iscsi_unregister_transport(&beiscsi_iscsi_transport);
3390}
3391
3392module_init(beiscsi_module_init);
3393module_exit(beiscsi_module_exit);
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h
new file mode 100644
index 000000000000..2520c39c594d
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_main.h
@@ -0,0 +1,833 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20
21#ifndef _BEISCSI_MAIN_
22#define _BEISCSI_MAIN_
23
24
25#include <linux/kernel.h>
26#include <linux/pci.h>
27#include <linux/in.h>
28#include <linux/blk-iopoll.h>
29#include <scsi/scsi.h>
30#include <scsi/scsi_cmnd.h>
31#include <scsi/scsi_device.h>
32#include <scsi/scsi_host.h>
33#include <scsi/iscsi_proto.h>
34#include <scsi/libiscsi.h>
35#include <scsi/scsi_transport_iscsi.h>
36
37#include "be.h"
38
39
40
41#define DRV_NAME "be2iscsi"
42#define BUILD_STR "2.0.527.0"
43
44#define BE_NAME "ServerEngines BladeEngine2" \
45 "Linux iSCSI Driver version" BUILD_STR
46#define DRV_DESC BE_NAME " " "Driver"
47
48#define BE_VENDOR_ID 0x19A2
49#define BE_DEVICE_ID1 0x212
50#define OC_DEVICE_ID1 0x702
51#define OC_DEVICE_ID2 0x703
52
53#define BE2_MAX_SESSIONS 64
54#define BE2_CMDS_PER_CXN 128
55#define BE2_LOGOUTS BE2_MAX_SESSIONS
56#define BE2_TMFS 16
57#define BE2_NOPOUT_REQ 16
58#define BE2_ASYNCPDUS BE2_MAX_SESSIONS
59#define BE2_MAX_ICDS 2048
60#define BE2_SGE 32
61#define BE2_DEFPDU_HDR_SZ 64
62#define BE2_DEFPDU_DATA_SZ 8192
63#define BE2_IO_DEPTH \
64 (BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ))
65
66#define BEISCSI_SGLIST_ELEMENTS BE2_SGE
67
68#define BEISCSI_MAX_CMNDS 1024 /* Max IO's per Ctrlr sht->can_queue */
69#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */
70#define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */
71
72#define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */
73#define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */
74#define BEISCSI_NUM_DEVICES_SUPPORTED 0x01
75#define BEISCSI_MAX_FRAGS_INIT 192
76#define BE_NUM_MSIX_ENTRIES 1
77#define MPU_EP_SEMAPHORE 0xac
78
79#define BE_SENSE_INFO_SIZE 258
80#define BE_ISCSI_PDU_HEADER_SIZE 64
81#define BE_MIN_MEM_SIZE 16384
82
83#define IIOC_SCSI_DATA 0x05 /* Write Operation */
84
85#define DBG_LVL 0x00000001
86#define DBG_LVL_1 0x00000001
87#define DBG_LVL_2 0x00000002
88#define DBG_LVL_3 0x00000004
89#define DBG_LVL_4 0x00000008
90#define DBG_LVL_5 0x00000010
91#define DBG_LVL_6 0x00000020
92#define DBG_LVL_7 0x00000040
93#define DBG_LVL_8 0x00000080
94
95#define SE_DEBUG(debug_mask, fmt, args...) \
96do { \
97 if (debug_mask & DBG_LVL) { \
98 printk(KERN_ERR "(%s():%d):", __func__, __LINE__);\
99 printk(fmt, ##args); \
100 } \
101} while (0);
102
103/**
104 * hardware needs the async PDU buffers to be posted in multiples of 8
105 * So have atleast 8 of them by default
106 */
107
108#define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx)
109
110/********* Memory BAR register ************/
111#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
112/**
113 * Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
114 * Disable" may still globally block interrupts in addition to individual
115 * interrupt masks; a mechanism for the device driver to block all interrupts
116 * atomically without having to arbitrate for the PCI Interrupt Disable bit
117 * with the OS.
118 */
119#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */
120
121/********* ISR0 Register offset **********/
122#define CEV_ISR0_OFFSET 0xC18
123#define CEV_ISR_SIZE 4
124
125/**
126 * Macros for reading/writing a protection domain or CSR registers
127 * in BladeEngine.
128 */
129
130#define DB_TXULP0_OFFSET 0x40
131#define DB_RXULP0_OFFSET 0xA0
132/********* Event Q door bell *************/
133#define DB_EQ_OFFSET DB_CQ_OFFSET
134#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */
135/* Clear the interrupt for this eq */
136#define DB_EQ_CLR_SHIFT (9) /* bit 9 */
137/* Must be 1 */
138#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */
139/* Number of event entries processed */
140#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
141/* Rearm bit */
142#define DB_EQ_REARM_SHIFT (29) /* bit 29 */
143
144/********* Compl Q door bell *************/
145#define DB_CQ_OFFSET 0x120
146#define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */
147/* Number of event entries processed */
148#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
149/* Rearm bit */
150#define DB_CQ_REARM_SHIFT (29) /* bit 29 */
151
152#define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr)
153#define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\
154 (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id)
155#define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\
156 (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id)
157
158#define PAGES_REQUIRED(x) \
159 ((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE))
160
161enum be_mem_enum {
162 HWI_MEM_ADDN_CONTEXT,
163 HWI_MEM_CQ,
164 HWI_MEM_EQ,
165 HWI_MEM_WRB,
166 HWI_MEM_WRBH,
167 HWI_MEM_SGLH, /* 5 */
168 HWI_MEM_SGE,
169 HWI_MEM_ASYNC_HEADER_BUF,
170 HWI_MEM_ASYNC_DATA_BUF,
171 HWI_MEM_ASYNC_HEADER_RING,
172 HWI_MEM_ASYNC_DATA_RING, /* 10 */
173 HWI_MEM_ASYNC_HEADER_HANDLE,
174 HWI_MEM_ASYNC_DATA_HANDLE,
175 HWI_MEM_ASYNC_PDU_CONTEXT,
176 ISCSI_MEM_GLOBAL_HEADER,
177 SE_MEM_MAX /* 15 */
178};
179
180struct be_bus_address32 {
181 unsigned int address_lo;
182 unsigned int address_hi;
183};
184
185struct be_bus_address64 {
186 unsigned long long address;
187};
188
189struct be_bus_address {
190 union {
191 struct be_bus_address32 a32;
192 struct be_bus_address64 a64;
193 } u;
194};
195
196struct mem_array {
197 struct be_bus_address bus_address; /* Bus address of location */
198 void *virtual_address; /* virtual address to the location */
199 unsigned int size; /* Size required by memory block */
200};
201
202struct be_mem_descriptor {
203 unsigned int index; /* Index of this memory parameter */
204 unsigned int category; /* type indicates cached/non-cached */
205 unsigned int num_elements; /* number of elements in this
206 * descriptor
207 */
208 unsigned int alignment_mask; /* Alignment mask for this block */
209 unsigned int size_in_bytes; /* Size required by memory block */
210 struct mem_array *mem_array;
211};
212
213struct sgl_handle {
214 unsigned int sgl_index;
215 struct iscsi_sge *pfrag;
216};
217
218struct hba_parameters {
219 unsigned int ios_per_ctrl;
220 unsigned int cxns_per_ctrl;
221 unsigned int asyncpdus_per_ctrl;
222 unsigned int icds_per_ctrl;
223 unsigned int num_sge_per_io;
224 unsigned int defpdu_hdr_sz;
225 unsigned int defpdu_data_sz;
226 unsigned int num_cq_entries;
227 unsigned int num_eq_entries;
228 unsigned int wrbs_per_cxn;
229 unsigned int crashmode;
230 unsigned int hba_num;
231
232 unsigned int mgmt_ws_sz;
233 unsigned int hwi_ws_sz;
234
235 unsigned int eto;
236 unsigned int ldto;
237
238 unsigned int dbg_flags;
239 unsigned int num_cxn;
240
241 unsigned int eq_timer;
242 /**
243 * These are calculated from other params. They're here
244 * for debug purposes
245 */
246 unsigned int num_mcc_pages;
247 unsigned int num_mcc_cq_pages;
248 unsigned int num_cq_pages;
249 unsigned int num_eq_pages;
250
251 unsigned int num_async_pdu_buf_pages;
252 unsigned int num_async_pdu_buf_sgl_pages;
253 unsigned int num_async_pdu_buf_cq_pages;
254
255 unsigned int num_async_pdu_hdr_pages;
256 unsigned int num_async_pdu_hdr_sgl_pages;
257 unsigned int num_async_pdu_hdr_cq_pages;
258
259 unsigned int num_sge;
260};
261
262struct beiscsi_hba {
263 struct hba_parameters params;
264 struct hwi_controller *phwi_ctrlr;
265 unsigned int mem_req[SE_MEM_MAX];
266 /* PCI BAR mapped addresses */
267 u8 __iomem *csr_va; /* CSR */
268 u8 __iomem *db_va; /* Door Bell */
269 u8 __iomem *pci_va; /* PCI Config */
270 struct be_bus_address csr_pa; /* CSR */
271 struct be_bus_address db_pa; /* CSR */
272 struct be_bus_address pci_pa; /* CSR */
273 /* PCI representation of our HBA */
274 struct pci_dev *pcidev;
275 unsigned int state;
276 unsigned short asic_revision;
277 struct blk_iopoll iopoll;
278 struct be_mem_descriptor *init_mem;
279
280 unsigned short io_sgl_alloc_index;
281 unsigned short io_sgl_free_index;
282 unsigned short io_sgl_hndl_avbl;
283 struct sgl_handle **io_sgl_hndl_base;
284
285 unsigned short eh_sgl_alloc_index;
286 unsigned short eh_sgl_free_index;
287 unsigned short eh_sgl_hndl_avbl;
288 struct sgl_handle **eh_sgl_hndl_base;
289 spinlock_t io_sgl_lock;
290 spinlock_t mgmt_sgl_lock;
291 spinlock_t isr_lock;
292 unsigned int age;
293 unsigned short avlbl_cids;
294 unsigned short cid_alloc;
295 unsigned short cid_free;
296 struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2];
297 struct list_head hba_queue;
298 unsigned short *cid_array;
299 struct iscsi_endpoint **ep_array;
300 struct Scsi_Host *shost;
301 struct {
302 /**
303 * group together since they are used most frequently
304 * for cid to cri conversion
305 */
306 unsigned int iscsi_cid_start;
307 unsigned int phys_port;
308
309 unsigned int isr_offset;
310 unsigned int iscsi_icd_start;
311 unsigned int iscsi_cid_count;
312 unsigned int iscsi_icd_count;
313 unsigned int pci_function;
314
315 unsigned short cid_alloc;
316 unsigned short cid_free;
317 unsigned short avlbl_cids;
318 spinlock_t cid_lock;
319 } fw_config;
320
321 u8 mac_address[ETH_ALEN];
322 unsigned short todo_cq;
323 unsigned short todo_mcc_cq;
324 char wq_name[20];
325 struct workqueue_struct *wq; /* The actuak work queue */
326 struct work_struct work_cqs; /* The work being queued */
327 struct be_ctrl_info ctrl;
328};
329
330/**
331 * struct beiscsi_conn - iscsi connection structure
332 */
333struct beiscsi_conn {
334 struct iscsi_conn *conn;
335 struct beiscsi_hba *phba;
336 u32 exp_statsn;
337 u32 beiscsi_conn_cid;
338 struct beiscsi_endpoint *ep;
339 unsigned short login_in_progress;
340 struct sgl_handle *plogin_sgl_handle;
341};
342
343/* This structure is used by the chip */
344struct pdu_data_out {
345 u32 dw[12];
346};
347/**
348 * Pseudo amap definition in which each bit of the actual structure is defined
349 * as a byte: used to calculate offset/shift/mask of each field
350 */
351struct amap_pdu_data_out {
352 u8 opcode[6]; /* opcode */
353 u8 rsvd0[2]; /* should be 0 */
354 u8 rsvd1[7];
355 u8 final_bit; /* F bit */
356 u8 rsvd2[16];
357 u8 ahs_length[8]; /* no AHS */
358 u8 data_len_hi[8];
359 u8 data_len_lo[16]; /* DataSegmentLength */
360 u8 lun[64];
361 u8 itt[32]; /* ITT; initiator task tag */
362 u8 ttt[32]; /* TTT; valid for R2T or 0xffffffff */
363 u8 rsvd3[32];
364 u8 exp_stat_sn[32];
365 u8 rsvd4[32];
366 u8 data_sn[32];
367 u8 buffer_offset[32];
368 u8 rsvd5[32];
369};
370
371struct be_cmd_bhs {
372 struct iscsi_cmd iscsi_hdr;
373 unsigned char pad1[16];
374 struct pdu_data_out iscsi_data_pdu;
375 unsigned char pad2[BE_SENSE_INFO_SIZE -
376 sizeof(struct pdu_data_out)];
377};
378
379struct beiscsi_io_task {
380 struct wrb_handle *pwrb_handle;
381 struct sgl_handle *psgl_handle;
382 struct beiscsi_conn *conn;
383 struct scsi_cmnd *scsi_cmnd;
384 unsigned int cmd_sn;
385 unsigned int flags;
386 unsigned short cid;
387 unsigned short header_len;
388
389 unsigned int alloc_size;
390 struct be_cmd_bhs *cmd_bhs;
391 struct be_bus_address bhs_pa;
392 unsigned short bhs_len;
393};
394
395struct be_nonio_bhs {
396 struct iscsi_hdr iscsi_hdr;
397 unsigned char pad1[16];
398 struct pdu_data_out iscsi_data_pdu;
399 unsigned char pad2[BE_SENSE_INFO_SIZE -
400 sizeof(struct pdu_data_out)];
401};
402
403struct be_status_bhs {
404 struct iscsi_cmd iscsi_hdr;
405 unsigned char pad1[16];
406 /**
407 * The plus 2 below is to hold the sense info length that gets
408 * DMA'ed by RxULP
409 */
410 unsigned char sense_info[BE_SENSE_INFO_SIZE];
411};
412
413struct iscsi_sge {
414 u32 dw[4];
415};
416
417/**
418 * Pseudo amap definition in which each bit of the actual structure is defined
419 * as a byte: used to calculate offset/shift/mask of each field
420 */
421struct amap_iscsi_sge {
422 u8 addr_hi[32];
423 u8 addr_lo[32];
424 u8 sge_offset[22]; /* DWORD 2 */
425 u8 rsvd0[9]; /* DWORD 2 */
426 u8 last_sge; /* DWORD 2 */
427 u8 len[17]; /* DWORD 3 */
428 u8 rsvd1[15]; /* DWORD 3 */
429};
430
431struct beiscsi_offload_params {
432 u32 dw[5];
433};
434
435#define OFFLD_PARAMS_ERL 0x00000003
436#define OFFLD_PARAMS_DDE 0x00000004
437#define OFFLD_PARAMS_HDE 0x00000008
438#define OFFLD_PARAMS_IR2T 0x00000010
439#define OFFLD_PARAMS_IMD 0x00000020
440
441/**
442 * Pseudo amap definition in which each bit of the actual structure is defined
443 * as a byte: used to calculate offset/shift/mask of each field
444 */
445struct amap_beiscsi_offload_params {
446 u8 max_burst_length[32];
447 u8 max_send_data_segment_length[32];
448 u8 first_burst_length[32];
449 u8 erl[2];
450 u8 dde[1];
451 u8 hde[1];
452 u8 ir2t[1];
453 u8 imd[1];
454 u8 pad[26];
455 u8 exp_statsn[32];
456};
457
458/* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
459 struct beiscsi_hba *phba, struct sol_cqe *psol);*/
460
461struct async_pdu_handle {
462 struct list_head link;
463 struct be_bus_address pa;
464 void *pbuffer;
465 unsigned int consumed;
466 unsigned char index;
467 unsigned char is_header;
468 unsigned short cri;
469 unsigned long buffer_len;
470};
471
472struct hwi_async_entry {
473 struct {
474 unsigned char hdr_received;
475 unsigned char hdr_len;
476 unsigned short bytes_received;
477 unsigned int bytes_needed;
478 struct list_head list;
479 } wait_queue;
480
481 struct list_head header_busy_list;
482 struct list_head data_busy_list;
483};
484
485#define BE_MIN_ASYNC_ENTRIES 128
486
487struct hwi_async_pdu_context {
488 struct {
489 struct be_bus_address pa_base;
490 void *va_base;
491 void *ring_base;
492 struct async_pdu_handle *handle_base;
493
494 unsigned int host_write_ptr;
495 unsigned int ep_read_ptr;
496 unsigned int writables;
497
498 unsigned int free_entries;
499 unsigned int busy_entries;
500 unsigned int buffer_size;
501 unsigned int num_entries;
502
503 struct list_head free_list;
504 } async_header;
505
506 struct {
507 struct be_bus_address pa_base;
508 void *va_base;
509 void *ring_base;
510 struct async_pdu_handle *handle_base;
511
512 unsigned int host_write_ptr;
513 unsigned int ep_read_ptr;
514 unsigned int writables;
515
516 unsigned int free_entries;
517 unsigned int busy_entries;
518 unsigned int buffer_size;
519 struct list_head free_list;
520 unsigned int num_entries;
521 } async_data;
522
523 /**
524 * This is a varying size list! Do not add anything
525 * after this entry!!
526 */
527 struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES];
528};
529
530#define PDUCQE_CODE_MASK 0x0000003F
531#define PDUCQE_DPL_MASK 0xFFFF0000
532#define PDUCQE_INDEX_MASK 0x0000FFFF
533
534struct i_t_dpdu_cqe {
535 u32 dw[4];
536} __packed;
537
538/**
539 * Pseudo amap definition in which each bit of the actual structure is defined
540 * as a byte: used to calculate offset/shift/mask of each field
541 */
542struct amap_i_t_dpdu_cqe {
543 u8 db_addr_hi[32];
544 u8 db_addr_lo[32];
545 u8 code[6];
546 u8 cid[10];
547 u8 dpl[16];
548 u8 index[16];
549 u8 num_cons[10];
550 u8 rsvd0[4];
551 u8 final;
552 u8 valid;
553} __packed;
554
555#define CQE_VALID_MASK 0x80000000
556#define CQE_CODE_MASK 0x0000003F
557#define CQE_CID_MASK 0x0000FFC0
558
559#define EQE_VALID_MASK 0x00000001
560#define EQE_MAJORCODE_MASK 0x0000000E
561#define EQE_RESID_MASK 0xFFFF0000
562
563struct be_eq_entry {
564 u32 dw[1];
565} __packed;
566
567/**
568 * Pseudo amap definition in which each bit of the actual structure is defined
569 * as a byte: used to calculate offset/shift/mask of each field
570 */
571struct amap_eq_entry {
572 u8 valid; /* DWORD 0 */
573 u8 major_code[3]; /* DWORD 0 */
574 u8 minor_code[12]; /* DWORD 0 */
575 u8 resource_id[16]; /* DWORD 0 */
576
577} __packed;
578
579struct cq_db {
580 u32 dw[1];
581} __packed;
582
583/**
584 * Pseudo amap definition in which each bit of the actual structure is defined
585 * as a byte: used to calculate offset/shift/mask of each field
586 */
587struct amap_cq_db {
588 u8 qid[10];
589 u8 event[1];
590 u8 rsvd0[5];
591 u8 num_popped[13];
592 u8 rearm[1];
593 u8 rsvd1[2];
594} __packed;
595
596void beiscsi_process_eq(struct beiscsi_hba *phba);
597
598
599struct iscsi_wrb {
600 u32 dw[16];
601} __packed;
602
603#define WRB_TYPE_MASK 0xF0000000
604
605/**
606 * Pseudo amap definition in which each bit of the actual structure is defined
607 * as a byte: used to calculate offset/shift/mask of each field
608 */
609struct amap_iscsi_wrb {
610 u8 lun[14]; /* DWORD 0 */
611 u8 lt; /* DWORD 0 */
612 u8 invld; /* DWORD 0 */
613 u8 wrb_idx[8]; /* DWORD 0 */
614 u8 dsp; /* DWORD 0 */
615 u8 dmsg; /* DWORD 0 */
616 u8 undr_run; /* DWORD 0 */
617 u8 over_run; /* DWORD 0 */
618 u8 type[4]; /* DWORD 0 */
619 u8 ptr2nextwrb[8]; /* DWORD 1 */
620 u8 r2t_exp_dtl[24]; /* DWORD 1 */
621 u8 sgl_icd_idx[12]; /* DWORD 2 */
622 u8 rsvd0[20]; /* DWORD 2 */
623 u8 exp_data_sn[32]; /* DWORD 3 */
624 u8 iscsi_bhs_addr_hi[32]; /* DWORD 4 */
625 u8 iscsi_bhs_addr_lo[32]; /* DWORD 5 */
626 u8 cmdsn_itt[32]; /* DWORD 6 */
627 u8 dif_ref_tag[32]; /* DWORD 7 */
628 u8 sge0_addr_hi[32]; /* DWORD 8 */
629 u8 sge0_addr_lo[32]; /* DWORD 9 */
630 u8 sge0_offset[22]; /* DWORD 10 */
631 u8 pbs; /* DWORD 10 */
632 u8 dif_mode[2]; /* DWORD 10 */
633 u8 rsvd1[6]; /* DWORD 10 */
634 u8 sge0_last; /* DWORD 10 */
635 u8 sge0_len[17]; /* DWORD 11 */
636 u8 dif_meta_tag[14]; /* DWORD 11 */
637 u8 sge0_in_ddr; /* DWORD 11 */
638 u8 sge1_addr_hi[32]; /* DWORD 12 */
639 u8 sge1_addr_lo[32]; /* DWORD 13 */
640 u8 sge1_r2t_offset[22]; /* DWORD 14 */
641 u8 rsvd2[9]; /* DWORD 14 */
642 u8 sge1_last; /* DWORD 14 */
643 u8 sge1_len[17]; /* DWORD 15 */
644 u8 ref_sgl_icd_idx[12]; /* DWORD 15 */
645 u8 rsvd3[2]; /* DWORD 15 */
646 u8 sge1_in_ddr; /* DWORD 15 */
647
648} __packed;
649
650struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
651 int index);
652void
653free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
654
655struct pdu_nop_out {
656 u32 dw[12];
657};
658
659/**
660 * Pseudo amap definition in which each bit of the actual structure is defined
661 * as a byte: used to calculate offset/shift/mask of each field
662 */
663struct amap_pdu_nop_out {
664 u8 opcode[6]; /* opcode 0x00 */
665 u8 i_bit; /* I Bit */
666 u8 x_bit; /* reserved; should be 0 */
667 u8 fp_bit_filler1[7];
668 u8 f_bit; /* always 1 */
669 u8 reserved1[16];
670 u8 ahs_length[8]; /* no AHS */
671 u8 data_len_hi[8];
672 u8 data_len_lo[16]; /* DataSegmentLength */
673 u8 lun[64];
674 u8 itt[32]; /* initiator id for ping or 0xffffffff */
675 u8 ttt[32]; /* target id for ping or 0xffffffff */
676 u8 cmd_sn[32];
677 u8 exp_stat_sn[32];
678 u8 reserved5[128];
679};
680
681#define PDUBASE_OPCODE_MASK 0x0000003F
682#define PDUBASE_DATALENHI_MASK 0x0000FF00
683#define PDUBASE_DATALENLO_MASK 0xFFFF0000
684
685struct pdu_base {
686 u32 dw[16];
687} __packed;
688
689/**
690 * Pseudo amap definition in which each bit of the actual structure is defined
691 * as a byte: used to calculate offset/shift/mask of each field
692 */
693struct amap_pdu_base {
694 u8 opcode[6];
695 u8 i_bit; /* immediate bit */
696 u8 x_bit; /* reserved, always 0 */
697 u8 reserved1[24]; /* opcode-specific fields */
698 u8 ahs_length[8]; /* length units is 4 byte words */
699 u8 data_len_hi[8];
700 u8 data_len_lo[16]; /* DatasegmentLength */
701 u8 lun[64]; /* lun or opcode-specific fields */
702 u8 itt[32]; /* initiator task tag */
703 u8 reserved4[224];
704};
705
706struct iscsi_target_context_update_wrb {
707 u32 dw[16];
708} __packed;
709
710/**
711 * Pseudo amap definition in which each bit of the actual structure is defined
712 * as a byte: used to calculate offset/shift/mask of each field
713 */
714struct amap_iscsi_target_context_update_wrb {
715 u8 lun[14]; /* DWORD 0 */
716 u8 lt; /* DWORD 0 */
717 u8 invld; /* DWORD 0 */
718 u8 wrb_idx[8]; /* DWORD 0 */
719 u8 dsp; /* DWORD 0 */
720 u8 dmsg; /* DWORD 0 */
721 u8 undr_run; /* DWORD 0 */
722 u8 over_run; /* DWORD 0 */
723 u8 type[4]; /* DWORD 0 */
724 u8 ptr2nextwrb[8]; /* DWORD 1 */
725 u8 max_burst_length[19]; /* DWORD 1 */
726 u8 rsvd0[5]; /* DWORD 1 */
727 u8 rsvd1[15]; /* DWORD 2 */
728 u8 max_send_data_segment_length[17]; /* DWORD 2 */
729 u8 first_burst_length[14]; /* DWORD 3 */
730 u8 rsvd2[2]; /* DWORD 3 */
731 u8 tx_wrbindex_drv_msg[8]; /* DWORD 3 */
732 u8 rsvd3[5]; /* DWORD 3 */
733 u8 session_state[3]; /* DWORD 3 */
734 u8 rsvd4[16]; /* DWORD 4 */
735 u8 tx_jumbo; /* DWORD 4 */
736 u8 hde; /* DWORD 4 */
737 u8 dde; /* DWORD 4 */
738 u8 erl[2]; /* DWORD 4 */
739 u8 domain_id[5]; /* DWORD 4 */
740 u8 mode; /* DWORD 4 */
741 u8 imd; /* DWORD 4 */
742 u8 ir2t; /* DWORD 4 */
743 u8 notpredblq[2]; /* DWORD 4 */
744 u8 compltonack; /* DWORD 4 */
745 u8 stat_sn[32]; /* DWORD 5 */
746 u8 pad_buffer_addr_hi[32]; /* DWORD 6 */
747 u8 pad_buffer_addr_lo[32]; /* DWORD 7 */
748 u8 pad_addr_hi[32]; /* DWORD 8 */
749 u8 pad_addr_lo[32]; /* DWORD 9 */
750 u8 rsvd5[32]; /* DWORD 10 */
751 u8 rsvd6[32]; /* DWORD 11 */
752 u8 rsvd7[32]; /* DWORD 12 */
753 u8 rsvd8[32]; /* DWORD 13 */
754 u8 rsvd9[32]; /* DWORD 14 */
755 u8 rsvd10[32]; /* DWORD 15 */
756
757} __packed;
758
759struct be_ring {
760 u32 pages; /* queue size in pages */
761 u32 id; /* queue id assigned by beklib */
762 u32 num; /* number of elements in queue */
763 u32 cidx; /* consumer index */
764 u32 pidx; /* producer index -- not used by most rings */
765 u32 item_size; /* size in bytes of one object */
766
767 void *va; /* The virtual address of the ring. This
768 * should be last to allow 32 & 64 bit debugger
769 * extensions to work.
770 */
771};
772
773struct hwi_wrb_context {
774 struct list_head wrb_handle_list;
775 struct list_head wrb_handle_drvr_list;
776 struct wrb_handle **pwrb_handle_base;
777 struct wrb_handle **pwrb_handle_basestd;
778 struct iscsi_wrb *plast_wrb;
779 unsigned short alloc_index;
780 unsigned short free_index;
781 unsigned short wrb_handles_available;
782 unsigned short cid;
783};
784
785struct hwi_controller {
786 struct list_head io_sgl_list;
787 struct list_head eh_sgl_list;
788 struct sgl_handle *psgl_handle_base;
789 unsigned int wrb_mem_index;
790
791 struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2];
792 struct mcc_wrb *pmcc_wrb_base;
793 struct be_ring default_pdu_hdr;
794 struct be_ring default_pdu_data;
795 struct hwi_context_memory *phwi_ctxt;
796 unsigned short cq_errors[CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN];
797};
798
799enum hwh_type_enum {
800 HWH_TYPE_IO = 1,
801 HWH_TYPE_LOGOUT = 2,
802 HWH_TYPE_TMF = 3,
803 HWH_TYPE_NOP = 4,
804 HWH_TYPE_IO_RD = 5,
805 HWH_TYPE_LOGIN = 11,
806 HWH_TYPE_INVALID = 0xFFFFFFFF
807};
808
809struct wrb_handle {
810 enum hwh_type_enum type;
811 unsigned short wrb_index;
812 unsigned short nxt_wrb_index;
813
814 struct iscsi_task *pio_handle;
815 struct iscsi_wrb *pwrb;
816};
817
818struct hwi_context_memory {
819 struct be_eq_obj be_eq;
820 struct be_queue_info be_cq;
821 struct be_queue_info be_mcc_cq;
822 struct be_queue_info be_mcc;
823
824 struct be_queue_info be_def_hdrq;
825 struct be_queue_info be_def_dataq;
826
827 struct be_queue_info be_wrbq[BE2_MAX_SESSIONS];
828 struct be_mcc_wrb_context *pbe_mcc_context;
829
830 struct hwi_async_pdu_context *pasync_ctx;
831};
832
833#endif
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
new file mode 100644
index 000000000000..12e644fc746e
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -0,0 +1,321 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20
21#include "be_mgmt.h"
22#include "be_iscsi.h"
23
24unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
25 struct beiscsi_hba *phba)
26{
27 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
28 struct be_fw_cfg *req = embedded_payload(wrb);
29 int status = 0;
30
31 spin_lock(&ctrl->mbox_lock);
32 memset(wrb, 0, sizeof(*wrb));
33
34 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
35
36 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
37 OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
38
39 status = be_mbox_notify(ctrl);
40 if (!status) {
41 struct be_fw_cfg *pfw_cfg;
42 pfw_cfg = req;
43 phba->fw_config.phys_port = pfw_cfg->phys_port;
44 phba->fw_config.iscsi_icd_start =
45 pfw_cfg->ulp[0].icd_base;
46 phba->fw_config.iscsi_icd_count =
47 pfw_cfg->ulp[0].icd_count;
48 phba->fw_config.iscsi_cid_start =
49 pfw_cfg->ulp[0].sq_base;
50 phba->fw_config.iscsi_cid_count =
51 pfw_cfg->ulp[0].sq_count;
52 } else {
53 shost_printk(KERN_WARNING, phba->shost,
54 "Failed in mgmt_get_fw_config \n");
55 }
56
57 spin_unlock(&ctrl->mbox_lock);
58 return status;
59}
60
61unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl)
62{
63 struct be_dma_mem nonemb_cmd;
64 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
65 struct be_mgmt_controller_attributes *req;
66 struct be_sge *sge = nonembedded_sgl(wrb);
67 int status = 0;
68
69 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
70 sizeof(struct be_mgmt_controller_attributes),
71 &nonemb_cmd.dma);
72 if (nonemb_cmd.va == NULL) {
73 SE_DEBUG(DBG_LVL_1,
74 "Failed to allocate memory for mgmt_check_supported_fw"
75 "\n");
76 return -1;
77 }
78 nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes);
79 req = nonemb_cmd.va;
80 spin_lock(&ctrl->mbox_lock);
81 memset(wrb, 0, sizeof(*wrb));
82 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
83 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
84 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req));
85 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
86 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
87 sge->len = cpu_to_le32(nonemb_cmd.size);
88
89 status = be_mbox_notify(ctrl);
90 if (!status) {
91 struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va;
92 SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n",
93 resp->params.hba_attribs.flashrom_version_string);
94 SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n",
95 resp->params.hba_attribs.firmware_version_string);
96 SE_DEBUG(DBG_LVL_8,
97 "Developer Build, not performing version check...\n");
98
99 } else
100 SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n");
101 if (nonemb_cmd.va)
102 pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
103 nonemb_cmd.va, nonemb_cmd.dma);
104
105 spin_unlock(&ctrl->mbox_lock);
106 return status;
107}
108
109unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
110{
111 struct be_ctrl_info *ctrl = &phba->ctrl;
112 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
113 struct iscsi_cleanup_req *req = embedded_payload(wrb);
114 int status = 0;
115
116 spin_lock(&ctrl->mbox_lock);
117 memset(wrb, 0, sizeof(*wrb));
118
119 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
120 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
121 OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
122
123 req->chute = chute;
124 req->hdr_ring_id = 0;
125 req->data_ring_id = 0;
126
127 status = be_mbox_notify(ctrl);
128 if (status)
129 shost_printk(KERN_WARNING, phba->shost,
130 " mgmt_epfw_cleanup , FAILED\n");
131 spin_unlock(&ctrl->mbox_lock);
132 return status;
133}
134
135unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
136 unsigned int icd, unsigned int cid)
137{
138 struct be_dma_mem nonemb_cmd;
139 struct be_ctrl_info *ctrl = &phba->ctrl;
140 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
141 struct be_sge *sge = nonembedded_sgl(wrb);
142 struct invalidate_commands_params_in *req;
143 int status = 0;
144
145 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
146 sizeof(struct invalidate_commands_params_in),
147 &nonemb_cmd.dma);
148 if (nonemb_cmd.va == NULL) {
149 SE_DEBUG(DBG_LVL_1,
150 "Failed to allocate memory for"
151 "mgmt_invalidate_icds \n");
152 return -1;
153 }
154 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
155 req = nonemb_cmd.va;
156 spin_lock(&ctrl->mbox_lock);
157 memset(wrb, 0, sizeof(*wrb));
158
159 be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
160 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
161 OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
162 sizeof(*req));
163 req->ref_handle = 0;
164 req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
165 req->icd_count = 0;
166 req->table[req->icd_count].icd = icd;
167 req->table[req->icd_count].cid = cid;
168 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
169 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF);
170 sge->len = cpu_to_le32(nonemb_cmd.size);
171
172 status = be_mbox_notify(ctrl);
173 if (status)
174 SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n");
175 spin_unlock(&ctrl->mbox_lock);
176 if (nonemb_cmd.va)
177 pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
178 nonemb_cmd.va, nonemb_cmd.dma);
179 return status;
180}
181
182unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
183 struct beiscsi_endpoint *beiscsi_ep,
184 unsigned short cid,
185 unsigned short issue_reset,
186 unsigned short savecfg_flag)
187{
188 struct be_ctrl_info *ctrl = &phba->ctrl;
189 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
190 struct iscsi_invalidate_connection_params_in *req =
191 embedded_payload(wrb);
192 int status = 0;
193
194 spin_lock(&ctrl->mbox_lock);
195 memset(wrb, 0, sizeof(*wrb));
196
197 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
198 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
199 OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
200 sizeof(*req));
201 req->session_handle = beiscsi_ep->fw_handle;
202 req->cid = cid;
203 if (issue_reset)
204 req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST;
205 else
206 req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
207 req->save_cfg = savecfg_flag;
208 status = be_mbox_notify(ctrl);
209 if (status)
210 SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n");
211
212 spin_unlock(&ctrl->mbox_lock);
213 return status;
214}
215
216unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
217 unsigned short cid, unsigned int upload_flag)
218{
219 struct be_ctrl_info *ctrl = &phba->ctrl;
220 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
221 struct tcp_upload_params_in *req = embedded_payload(wrb);
222 int status = 0;
223
224 spin_lock(&ctrl->mbox_lock);
225 memset(wrb, 0, sizeof(*wrb));
226
227 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
228 be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
229 OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
230 req->id = (unsigned short)cid;
231 req->upload_type = (unsigned char)upload_flag;
232 status = be_mbox_notify(ctrl);
233 if (status)
234 SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n");
235 spin_unlock(&ctrl->mbox_lock);
236 return status;
237}
238
239int mgmt_open_connection(struct beiscsi_hba *phba,
240 struct sockaddr *dst_addr,
241 struct beiscsi_endpoint *beiscsi_ep)
242{
243 struct hwi_controller *phwi_ctrlr;
244 struct hwi_context_memory *phwi_context;
245 struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr;
246 struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr;
247 struct be_ctrl_info *ctrl = &phba->ctrl;
248 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
249 struct tcp_connect_and_offload_in *req = embedded_payload(wrb);
250 unsigned short def_hdr_id;
251 unsigned short def_data_id;
252 struct phys_addr template_address = { 0, 0 };
253 struct phys_addr *ptemplate_address;
254 int status = 0;
255 unsigned short cid = beiscsi_ep->ep_cid;
256
257 phwi_ctrlr = phba->phwi_ctrlr;
258 phwi_context = phwi_ctrlr->phwi_ctxt;
259 def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba);
260 def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba);
261
262 ptemplate_address = &template_address;
263 ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
264 spin_lock(&ctrl->mbox_lock);
265 memset(wrb, 0, sizeof(*wrb));
266
267 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
268 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
269 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
270 sizeof(*req));
271 if (dst_addr->sa_family == PF_INET) {
272 __be32 s_addr = daddr_in->sin_addr.s_addr;
273 req->ip_address.ip_type = BE2_IPV4;
274 req->ip_address.ip_address[0] = s_addr & 0x000000ff;
275 req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8;
276 req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16;
277 req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24;
278 req->tcp_port = ntohs(daddr_in->sin_port);
279 beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
280 beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
281 beiscsi_ep->ip_type = BE2_IPV4;
282 } else if (dst_addr->sa_family == PF_INET6) {
283 req->ip_address.ip_type = BE2_IPV6;
284 memcpy(&req->ip_address.ip_address,
285 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
286 req->tcp_port = ntohs(daddr_in6->sin6_port);
287 beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
288 memcpy(&beiscsi_ep->dst6_addr,
289 &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
290 beiscsi_ep->ip_type = BE2_IPV6;
291 } else{
292 shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n",
293 dst_addr->sa_family);
294 spin_unlock(&ctrl->mbox_lock);
295 return -EINVAL;
296
297 }
298 req->cid = cid;
299 req->cq_id = phwi_context->be_cq.id;
300 req->defq_id = def_hdr_id;
301 req->hdr_ring_id = def_hdr_id;
302 req->data_ring_id = def_data_id;
303 req->do_offload = 1;
304 req->dataout_template_pa.lo = ptemplate_address->lo;
305 req->dataout_template_pa.hi = ptemplate_address->hi;
306 status = be_mbox_notify(ctrl);
307 if (!status) {
308 struct iscsi_endpoint *ep;
309 struct tcp_connect_and_offload_out *ptcpcnct_out =
310 embedded_payload(wrb);
311
312 ep = phba->ep_array[ptcpcnct_out->cid];
313 beiscsi_ep = ep->dd_data;
314 beiscsi_ep->fw_handle = 0;
315 beiscsi_ep->cid_vld = 1;
316 SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
317 } else
318 SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed\n");
319 spin_unlock(&ctrl->mbox_lock);
320 return status;
321}
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
new file mode 100644
index 000000000000..00e816ee8070
--- /dev/null
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -0,0 +1,249 @@
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 * Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
11 *
12 * Contact Information:
13 * linux-drivers@serverengines.com
14 *
15 * ServerEngines
16 * 209 N. Fair Oaks Ave
17 * Sunnyvale, CA 94085
18 *
19 */
20
21#ifndef _BEISCSI_MGMT_
22#define _BEISCSI_MGMT_
23
24#include <linux/types.h>
25#include <linux/list.h>
26#include "be_iscsi.h"
27#include "be_main.h"
28
29/**
30 * Pseudo amap definition in which each bit of the actual structure is defined
31 * as a byte: used to calculate offset/shift/mask of each field
32 */
33struct amap_mcc_sge {
34 u8 pa_lo[32]; /* dword 0 */
35 u8 pa_hi[32]; /* dword 1 */
36 u8 length[32]; /* DWORD 2 */
37} __packed;
38
39/**
40 * Pseudo amap definition in which each bit of the actual structure is defined
41 * as a byte: used to calculate offset/shift/mask of each field
42 */
43struct amap_mcc_wrb_payload {
44 union {
45 struct amap_mcc_sge sgl[19];
46 u8 embedded[59 * 32]; /* DWORDS 57 to 115 */
47 } u;
48} __packed;
49
50/**
51 * Pseudo amap definition in which each bit of the actual structure is defined
52 * as a byte: used to calculate offset/shift/mask of each field
53 */
54struct amap_mcc_wrb {
55 u8 embedded; /* DWORD 0 */
56 u8 rsvd0[2]; /* DWORD 0 */
57 u8 sge_count[5]; /* DWORD 0 */
58 u8 rsvd1[16]; /* DWORD 0 */
59 u8 special[8]; /* DWORD 0 */
60 u8 payload_length[32];
61 u8 tag[64]; /* DWORD 2 */
62 u8 rsvd2[32]; /* DWORD 4 */
63 struct amap_mcc_wrb_payload payload;
64};
65
66struct mcc_sge {
67 u32 pa_lo; /* dword 0 */
68 u32 pa_hi; /* dword 1 */
69 u32 length; /* DWORD 2 */
70} __packed;
71
72struct mcc_wrb_payload {
73 union {
74 struct mcc_sge sgl[19];
75 u32 embedded[59]; /* DWORDS 57 to 115 */
76 } u;
77} __packed;
78
79#define MCC_WRB_EMBEDDED_MASK 0x00000001
80
81struct mcc_wrb {
82 u32 dw[0]; /* DWORD 0 */
83 u32 payload_length;
84 u32 tag[2]; /* DWORD 2 */
85 u32 rsvd2[1]; /* DWORD 4 */
86 struct mcc_wrb_payload payload;
87};
88
89unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
90int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr,
91 struct beiscsi_endpoint *beiscsi_ep);
92
93unsigned char mgmt_upload_connection(struct beiscsi_hba *phba,
94 unsigned short cid,
95 unsigned int upload_flag);
96unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
97 unsigned int icd, unsigned int cid);
98
99struct iscsi_invalidate_connection_params_in {
100 struct be_cmd_req_hdr hdr;
101 unsigned int session_handle;
102 unsigned short cid;
103 unsigned short unused;
104 unsigned short cleanup_type;
105 unsigned short save_cfg;
106} __packed;
107
108struct iscsi_invalidate_connection_params_out {
109 unsigned int session_handle;
110 unsigned short cid;
111 unsigned short unused;
112} __packed;
113
114union iscsi_invalidate_connection_params {
115 struct iscsi_invalidate_connection_params_in request;
116 struct iscsi_invalidate_connection_params_out response;
117} __packed;
118
119struct invalidate_command_table {
120 unsigned short icd;
121 unsigned short cid;
122} __packed;
123
124struct invalidate_commands_params_in {
125 struct be_cmd_req_hdr hdr;
126 unsigned int ref_handle;
127 unsigned int icd_count;
128 struct invalidate_command_table table[128];
129 unsigned short cleanup_type;
130 unsigned short unused;
131} __packed;
132
133struct invalidate_commands_params_out {
134 unsigned int ref_handle;
135 unsigned int icd_count;
136 unsigned int icd_status[128];
137} __packed;
138
139union invalidate_commands_params {
140 struct invalidate_commands_params_in request;
141 struct invalidate_commands_params_out response;
142} __packed;
143
144struct mgmt_hba_attributes {
145 u8 flashrom_version_string[32];
146 u8 manufacturer_name[32];
147 u32 supported_modes;
148 u8 seeprom_version_lo;
149 u8 seeprom_version_hi;
150 u8 rsvd0[2];
151 u32 fw_cmd_data_struct_version;
152 u32 ep_fw_data_struct_version;
153 u32 future_reserved[12];
154 u32 default_extended_timeout;
155 u8 controller_model_number[32];
156 u8 controller_description[64];
157 u8 controller_serial_number[32];
158 u8 ip_version_string[32];
159 u8 firmware_version_string[32];
160 u8 bios_version_string[32];
161 u8 redboot_version_string[32];
162 u8 driver_version_string[32];
163 u8 fw_on_flash_version_string[32];
164 u32 functionalities_supported;
165 u16 max_cdblength;
166 u8 asic_revision;
167 u8 generational_guid[16];
168 u8 hba_port_count;
169 u16 default_link_down_timeout;
170 u8 iscsi_ver_min_max;
171 u8 multifunction_device;
172 u8 cache_valid;
173 u8 hba_status;
174 u8 max_domains_supported;
175 u8 phy_port;
176 u32 firmware_post_status;
177 u32 hba_mtu[8];
178 u32 future_u32[4];
179} __packed;
180
181struct mgmt_controller_attributes {
182 struct mgmt_hba_attributes hba_attribs;
183 u16 pci_vendor_id;
184 u16 pci_device_id;
185 u16 pci_sub_vendor_id;
186 u16 pci_sub_system_id;
187 u8 pci_bus_number;
188 u8 pci_device_number;
189 u8 pci_function_number;
190 u8 interface_type;
191 u64 unique_identifier;
192 u8 netfilters;
193 u8 rsvd0[3];
194 u8 future_u32[4];
195} __packed;
196
197struct be_mgmt_controller_attributes {
198 struct be_cmd_req_hdr hdr;
199 struct mgmt_controller_attributes params;
200} __packed;
201
202struct be_mgmt_controller_attributes_resp {
203 struct be_cmd_resp_hdr hdr;
204 struct mgmt_controller_attributes params;
205} __packed;
206
207/* configuration management */
208
209#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
210
211/* MGMT CMD flags */
212
213#define MGMT_CMDH_FREE (1<<0)
214
215/* --- MGMT_ERROR_CODES --- */
216/* Error Codes returned in the status field of the CMD response header */
217#define MGMT_STATUS_SUCCESS 0 /* The CMD completed without errors */
218#define MGMT_STATUS_FAILED 1 /* Error status in the Status field of */
219 /* the CMD_RESPONSE_HEADER */
220
221#define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\
222 pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
223 bus_address.u.a32.address_lo; \
224 pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
225 bus_address.u.a32.address_hi; \
226}
227
228struct beiscsi_endpoint {
229 struct beiscsi_hba *phba;
230 struct beiscsi_sess *sess;
231 struct beiscsi_conn *conn;
232 unsigned short ip_type;
233 char dst6_addr[ISCSI_ADDRESS_BUF_LEN];
234 unsigned long dst_addr;
235 unsigned short ep_cid;
236 unsigned int fw_handle;
237 u16 dst_tcpport;
238 u16 cid_vld;
239};
240
241unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl,
242 struct beiscsi_hba *phba);
243
244unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba,
245 struct beiscsi_endpoint *beiscsi_ep,
246 unsigned short cid,
247 unsigned short issue_reset,
248 unsigned short savecfg_flag);
249#endif