diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/be2iscsi | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/be2iscsi')
-rw-r--r-- | drivers/scsi/be2iscsi/be.h | 45 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 330 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.h | 49 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 155 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.h | 2 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 1297 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.h | 85 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.c | 177 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_mgmt.h | 16 |
9 files changed, 1618 insertions, 538 deletions
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index b36020dcf012..136b49cea791 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -20,8 +20,14 @@ | |||
20 | 20 | ||
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/if_vlan.h> | 22 | #include <linux/if_vlan.h> |
23 | 23 | #include <linux/blk-iopoll.h> | |
24 | #define FW_VER_LEN 32 | 24 | #define FW_VER_LEN 32 |
25 | #define MCC_Q_LEN 128 | ||
26 | #define MCC_CQ_LEN 256 | ||
27 | #define MAX_MCC_CMD 16 | ||
28 | /* BladeEngine Generation numbers */ | ||
29 | #define BE_GEN2 2 | ||
30 | #define BE_GEN3 3 | ||
25 | 31 | ||
26 | struct be_dma_mem { | 32 | struct be_dma_mem { |
27 | void *va; | 33 | void *va; |
@@ -55,6 +61,11 @@ static inline void *queue_head_node(struct be_queue_info *q) | |||
55 | return q->dma_mem.va + q->head * q->entry_size; | 61 | return q->dma_mem.va + q->head * q->entry_size; |
56 | } | 62 | } |
57 | 63 | ||
64 | static inline void *queue_get_wrb(struct be_queue_info *q, unsigned int wrb_num) | ||
65 | { | ||
66 | return q->dma_mem.va + wrb_num * q->entry_size; | ||
67 | } | ||
68 | |||
58 | static inline void *queue_tail_node(struct be_queue_info *q) | 69 | static inline void *queue_tail_node(struct be_queue_info *q) |
59 | { | 70 | { |
60 | return q->dma_mem.va + q->tail * q->entry_size; | 71 | return q->dma_mem.va + q->tail * q->entry_size; |
@@ -74,18 +85,14 @@ static inline void queue_tail_inc(struct be_queue_info *q) | |||
74 | 85 | ||
75 | struct be_eq_obj { | 86 | struct be_eq_obj { |
76 | struct be_queue_info q; | 87 | struct be_queue_info q; |
77 | char desc[32]; | 88 | struct beiscsi_hba *phba; |
78 | 89 | struct be_queue_info *cq; | |
79 | /* Adaptive interrupt coalescing (AIC) info */ | 90 | struct blk_iopoll iopoll; |
80 | bool enable_aic; | ||
81 | u16 min_eqd; /* in usecs */ | ||
82 | u16 max_eqd; /* in usecs */ | ||
83 | u16 cur_eqd; /* in usecs */ | ||
84 | }; | 91 | }; |
85 | 92 | ||
86 | struct be_mcc_obj { | 93 | struct be_mcc_obj { |
87 | struct be_queue_info *q; | 94 | struct be_queue_info q; |
88 | struct be_queue_info *cq; | 95 | struct be_queue_info cq; |
89 | }; | 96 | }; |
90 | 97 | ||
91 | struct be_ctrl_info { | 98 | struct be_ctrl_info { |
@@ -106,15 +113,19 @@ struct be_ctrl_info { | |||
106 | spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ | 113 | spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ |
107 | spinlock_t mcc_cq_lock; | 114 | spinlock_t mcc_cq_lock; |
108 | 115 | ||
109 | /* MCC Async callback */ | 116 | wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1]; |
110 | void (*async_cb) (void *adapter, bool link_up); | 117 | unsigned int mcc_tag[MAX_MCC_CMD]; |
111 | void *adapter_ctxt; | 118 | unsigned int mcc_numtag[MAX_MCC_CMD + 1]; |
119 | unsigned short mcc_alloc_index; | ||
120 | unsigned short mcc_free_index; | ||
121 | unsigned int mcc_tag_available; | ||
112 | }; | 122 | }; |
113 | 123 | ||
114 | #include "be_cmds.h" | 124 | #include "be_cmds.h" |
115 | 125 | ||
116 | #define PAGE_SHIFT_4K 12 | 126 | #define PAGE_SHIFT_4K 12 |
117 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) | 127 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) |
128 | #define mcc_timeout 120000 /* 5s timeout */ | ||
118 | 129 | ||
119 | /* Returns number of pages spanned by the data starting at the given addr */ | 130 | /* Returns number of pages spanned by the data starting at the given addr */ |
120 | #define PAGES_4K_SPANNED(_address, size) \ | 131 | #define PAGES_4K_SPANNED(_address, size) \ |
@@ -176,8 +187,4 @@ static inline void swap_dws(void *wrb, int len) | |||
176 | } while (len); | 187 | } while (len); |
177 | #endif /* __BIG_ENDIAN */ | 188 | #endif /* __BIG_ENDIAN */ |
178 | } | 189 | } |
179 | |||
180 | extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | ||
181 | u16 num_popped); | ||
182 | |||
183 | #endif /* BEISCSI_H */ | 190 | #endif /* BEISCSI_H */ |
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 08007b6e42df..cda6642c7368 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -19,6 +19,55 @@ | |||
19 | #include "be_mgmt.h" | 19 | #include "be_mgmt.h" |
20 | #include "be_main.h" | 20 | #include "be_main.h" |
21 | 21 | ||
22 | void be_mcc_notify(struct beiscsi_hba *phba) | ||
23 | { | ||
24 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
25 | u32 val = 0; | ||
26 | |||
27 | val |= mccq->id & DB_MCCQ_RING_ID_MASK; | ||
28 | val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; | ||
29 | iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); | ||
30 | } | ||
31 | |||
32 | unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) | ||
33 | { | ||
34 | unsigned int tag = 0; | ||
35 | |||
36 | if (phba->ctrl.mcc_tag_available) { | ||
37 | tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; | ||
38 | phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; | ||
39 | phba->ctrl.mcc_numtag[tag] = 0; | ||
40 | } | ||
41 | if (tag) { | ||
42 | phba->ctrl.mcc_tag_available--; | ||
43 | if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) | ||
44 | phba->ctrl.mcc_alloc_index = 0; | ||
45 | else | ||
46 | phba->ctrl.mcc_alloc_index++; | ||
47 | } | ||
48 | return tag; | ||
49 | } | ||
50 | |||
51 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) | ||
52 | { | ||
53 | spin_lock(&ctrl->mbox_lock); | ||
54 | tag = tag & 0x000000FF; | ||
55 | ctrl->mcc_tag[ctrl->mcc_free_index] = tag; | ||
56 | if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) | ||
57 | ctrl->mcc_free_index = 0; | ||
58 | else | ||
59 | ctrl->mcc_free_index++; | ||
60 | ctrl->mcc_tag_available++; | ||
61 | spin_unlock(&ctrl->mbox_lock); | ||
62 | } | ||
63 | |||
64 | bool is_link_state_evt(u32 trailer) | ||
65 | { | ||
66 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | ||
67 | ASYNC_TRAILER_EVENT_CODE_MASK) == | ||
68 | ASYNC_EVENT_CODE_LINK_STATE); | ||
69 | } | ||
70 | |||
22 | static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) | 71 | static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) |
23 | { | 72 | { |
24 | if (compl->flags != 0) { | 73 | if (compl->flags != 0) { |
@@ -54,13 +103,74 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | |||
54 | return 0; | 103 | return 0; |
55 | } | 104 | } |
56 | 105 | ||
57 | static inline bool is_link_state_evt(u32 trailer) | 106 | int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, |
107 | struct be_mcc_compl *compl) | ||
58 | { | 108 | { |
59 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | 109 | u16 compl_status, extd_status; |
60 | ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE); | 110 | unsigned short tag; |
111 | |||
112 | be_dws_le_to_cpu(compl, 4); | ||
113 | |||
114 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | ||
115 | CQE_STATUS_COMPL_MASK; | ||
116 | /* The ctrl.mcc_numtag[tag] is filled with | ||
117 | * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status, | ||
118 | * [7:0] = compl_status | ||
119 | */ | ||
120 | tag = (compl->tag0 & 0x000000FF); | ||
121 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | ||
122 | CQE_STATUS_EXTD_MASK; | ||
123 | |||
124 | ctrl->mcc_numtag[tag] = 0x80000000; | ||
125 | ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000); | ||
126 | ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8; | ||
127 | ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF); | ||
128 | wake_up_interruptible(&ctrl->mcc_wait[tag]); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) | ||
133 | { | ||
134 | struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq; | ||
135 | struct be_mcc_compl *compl = queue_tail_node(mcc_cq); | ||
136 | |||
137 | if (be_mcc_compl_is_new(compl)) { | ||
138 | queue_tail_inc(mcc_cq); | ||
139 | return compl; | ||
140 | } | ||
141 | return NULL; | ||
142 | } | ||
143 | |||
144 | static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) | ||
145 | { | ||
146 | iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); | ||
61 | } | 147 | } |
62 | 148 | ||
63 | void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | 149 | void beiscsi_async_link_state_process(struct beiscsi_hba *phba, |
150 | struct be_async_event_link_state *evt) | ||
151 | { | ||
152 | switch (evt->port_link_status) { | ||
153 | case ASYNC_EVENT_LINK_DOWN: | ||
154 | SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d \n", | ||
155 | evt->physical_port); | ||
156 | phba->state |= BE_ADAPTER_LINK_DOWN; | ||
157 | iscsi_host_for_each_session(phba->shost, | ||
158 | be2iscsi_fail_session); | ||
159 | break; | ||
160 | case ASYNC_EVENT_LINK_UP: | ||
161 | phba->state = BE_ADAPTER_UP; | ||
162 | SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d \n", | ||
163 | evt->physical_port); | ||
164 | break; | ||
165 | default: | ||
166 | SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on" | ||
167 | "Physical Port %d \n", | ||
168 | evt->port_link_status, | ||
169 | evt->physical_port); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static void beiscsi_cq_notify(struct beiscsi_hba *phba, u16 qid, bool arm, | ||
64 | u16 num_popped) | 174 | u16 num_popped) |
65 | { | 175 | { |
66 | u32 val = 0; | 176 | u32 val = 0; |
@@ -68,7 +178,69 @@ void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | |||
68 | if (arm) | 178 | if (arm) |
69 | val |= 1 << DB_CQ_REARM_SHIFT; | 179 | val |= 1 << DB_CQ_REARM_SHIFT; |
70 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; | 180 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; |
71 | iowrite32(val, ctrl->db + DB_CQ_OFFSET); | 181 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); |
182 | } | ||
183 | |||
184 | |||
185 | int beiscsi_process_mcc(struct beiscsi_hba *phba) | ||
186 | { | ||
187 | struct be_mcc_compl *compl; | ||
188 | int num = 0, status = 0; | ||
189 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
190 | |||
191 | spin_lock_bh(&phba->ctrl.mcc_cq_lock); | ||
192 | while ((compl = be_mcc_compl_get(phba))) { | ||
193 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | ||
194 | /* Interpret flags as an async trailer */ | ||
195 | if (is_link_state_evt(compl->flags)) | ||
196 | /* Interpret compl as a async link evt */ | ||
197 | beiscsi_async_link_state_process(phba, | ||
198 | (struct be_async_event_link_state *) compl); | ||
199 | else | ||
200 | SE_DEBUG(DBG_LVL_1, | ||
201 | " Unsupported Async Event, flags" | ||
202 | " = 0x%08x \n", compl->flags); | ||
203 | |||
204 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { | ||
205 | status = be_mcc_compl_process(ctrl, compl); | ||
206 | atomic_dec(&phba->ctrl.mcc_obj.q.used); | ||
207 | } | ||
208 | be_mcc_compl_use(compl); | ||
209 | num++; | ||
210 | } | ||
211 | |||
212 | if (num) | ||
213 | beiscsi_cq_notify(phba, phba->ctrl.mcc_obj.cq.id, true, num); | ||
214 | |||
215 | spin_unlock_bh(&phba->ctrl.mcc_cq_lock); | ||
216 | return status; | ||
217 | } | ||
218 | |||
219 | /* Wait till no more pending mcc requests are present */ | ||
220 | static int be_mcc_wait_compl(struct beiscsi_hba *phba) | ||
221 | { | ||
222 | int i, status; | ||
223 | for (i = 0; i < mcc_timeout; i++) { | ||
224 | status = beiscsi_process_mcc(phba); | ||
225 | if (status) | ||
226 | return status; | ||
227 | |||
228 | if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0) | ||
229 | break; | ||
230 | udelay(100); | ||
231 | } | ||
232 | if (i == mcc_timeout) { | ||
233 | dev_err(&phba->pcidev->dev, "mccq poll timed out\n"); | ||
234 | return -1; | ||
235 | } | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* Notify MCC requests and wait for completion */ | ||
240 | int be_mcc_notify_wait(struct beiscsi_hba *phba) | ||
241 | { | ||
242 | be_mcc_notify(phba); | ||
243 | return be_mcc_wait_compl(phba); | ||
72 | } | 244 | } |
73 | 245 | ||
74 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | 246 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) |
@@ -142,6 +314,52 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) | |||
142 | return 0; | 314 | return 0; |
143 | } | 315 | } |
144 | 316 | ||
317 | /* | ||
318 | * Insert the mailbox address into the doorbell in two steps | ||
319 | * Polls on the mbox doorbell till a command completion (or a timeout) occurs | ||
320 | */ | ||
321 | static int be_mbox_notify_wait(struct beiscsi_hba *phba) | ||
322 | { | ||
323 | int status; | ||
324 | u32 val = 0; | ||
325 | void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET; | ||
326 | struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem; | ||
327 | struct be_mcc_mailbox *mbox = mbox_mem->va; | ||
328 | struct be_mcc_compl *compl = &mbox->compl; | ||
329 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
330 | |||
331 | val |= MPU_MAILBOX_DB_HI_MASK; | ||
332 | /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ | ||
333 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | ||
334 | iowrite32(val, db); | ||
335 | |||
336 | /* wait for ready to be set */ | ||
337 | status = be_mbox_db_ready_wait(ctrl); | ||
338 | if (status != 0) | ||
339 | return status; | ||
340 | |||
341 | val = 0; | ||
342 | /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ | ||
343 | val |= (u32)(mbox_mem->dma >> 4) << 2; | ||
344 | iowrite32(val, db); | ||
345 | |||
346 | status = be_mbox_db_ready_wait(ctrl); | ||
347 | if (status != 0) | ||
348 | return status; | ||
349 | |||
350 | /* A cq entry has been made now */ | ||
351 | if (be_mcc_compl_is_new(compl)) { | ||
352 | status = be_mcc_compl_process(ctrl, &mbox->compl); | ||
353 | be_mcc_compl_use(compl); | ||
354 | if (status) | ||
355 | return status; | ||
356 | } else { | ||
357 | dev_err(&phba->pcidev->dev, "invalid mailbox completion\n"); | ||
358 | return -1; | ||
359 | } | ||
360 | return 0; | ||
361 | } | ||
362 | |||
145 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | 363 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, |
146 | bool embedded, u8 sge_cnt) | 364 | bool embedded, u8 sge_cnt) |
147 | { | 365 | { |
@@ -203,6 +421,21 @@ struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) | |||
203 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; | 421 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; |
204 | } | 422 | } |
205 | 423 | ||
424 | struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba) | ||
425 | { | ||
426 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
427 | struct be_mcc_wrb *wrb; | ||
428 | |||
429 | BUG_ON(atomic_read(&mccq->used) >= mccq->len); | ||
430 | wrb = queue_head_node(mccq); | ||
431 | memset(wrb, 0, sizeof(*wrb)); | ||
432 | wrb->tag0 = (mccq->head & 0x000000FF) << 16; | ||
433 | queue_head_inc(mccq); | ||
434 | atomic_inc(&mccq->used); | ||
435 | return wrb; | ||
436 | } | ||
437 | |||
438 | |||
206 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | 439 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, |
207 | struct be_queue_info *eq, int eq_delay) | 440 | struct be_queue_info *eq, int eq_delay) |
208 | { | 441 | { |
@@ -212,6 +445,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
212 | struct be_dma_mem *q_mem = &eq->dma_mem; | 445 | struct be_dma_mem *q_mem = &eq->dma_mem; |
213 | int status; | 446 | int status; |
214 | 447 | ||
448 | SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_eq_create\n"); | ||
215 | spin_lock(&ctrl->mbox_lock); | 449 | spin_lock(&ctrl->mbox_lock); |
216 | memset(wrb, 0, sizeof(*wrb)); | 450 | memset(wrb, 0, sizeof(*wrb)); |
217 | 451 | ||
@@ -249,6 +483,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | |||
249 | int status; | 483 | int status; |
250 | u8 *endian_check; | 484 | u8 *endian_check; |
251 | 485 | ||
486 | SE_DEBUG(DBG_LVL_8, "In be_cmd_fw_initialize\n"); | ||
252 | spin_lock(&ctrl->mbox_lock); | 487 | spin_lock(&ctrl->mbox_lock); |
253 | memset(wrb, 0, sizeof(*wrb)); | 488 | memset(wrb, 0, sizeof(*wrb)); |
254 | 489 | ||
@@ -282,6 +517,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
282 | void *ctxt = &req->context; | 517 | void *ctxt = &req->context; |
283 | int status; | 518 | int status; |
284 | 519 | ||
520 | SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_cq_create \n"); | ||
285 | spin_lock(&ctrl->mbox_lock); | 521 | spin_lock(&ctrl->mbox_lock); |
286 | memset(wrb, 0, sizeof(*wrb)); | 522 | memset(wrb, 0, sizeof(*wrb)); |
287 | 523 | ||
@@ -289,7 +525,6 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
289 | 525 | ||
290 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 526 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
291 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); | 527 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); |
292 | |||
293 | if (!q_mem->va) | 528 | if (!q_mem->va) |
294 | SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n"); | 529 | SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n"); |
295 | 530 | ||
@@ -329,6 +564,53 @@ static u32 be_encoded_q_len(int q_len) | |||
329 | len_encoded = 0; | 564 | len_encoded = 0; |
330 | return len_encoded; | 565 | return len_encoded; |
331 | } | 566 | } |
567 | |||
568 | int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, | ||
569 | struct be_queue_info *mccq, | ||
570 | struct be_queue_info *cq) | ||
571 | { | ||
572 | struct be_mcc_wrb *wrb; | ||
573 | struct be_cmd_req_mcc_create *req; | ||
574 | struct be_dma_mem *q_mem = &mccq->dma_mem; | ||
575 | struct be_ctrl_info *ctrl; | ||
576 | void *ctxt; | ||
577 | int status; | ||
578 | |||
579 | spin_lock(&phba->ctrl.mbox_lock); | ||
580 | ctrl = &phba->ctrl; | ||
581 | wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
582 | req = embedded_payload(wrb); | ||
583 | ctxt = &req->context; | ||
584 | |||
585 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
586 | |||
587 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
588 | OPCODE_COMMON_MCC_CREATE, sizeof(*req)); | ||
589 | |||
590 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
591 | |||
592 | AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, | ||
593 | PCI_FUNC(phba->pcidev->devfn)); | ||
594 | AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); | ||
595 | AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, | ||
596 | be_encoded_q_len(mccq->len)); | ||
597 | AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); | ||
598 | |||
599 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
600 | |||
601 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
602 | |||
603 | status = be_mbox_notify_wait(phba); | ||
604 | if (!status) { | ||
605 | struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); | ||
606 | mccq->id = le16_to_cpu(resp->id); | ||
607 | mccq->created = true; | ||
608 | } | ||
609 | spin_unlock(&phba->ctrl.mbox_lock); | ||
610 | |||
611 | return status; | ||
612 | } | ||
613 | |||
332 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | 614 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, |
333 | int queue_type) | 615 | int queue_type) |
334 | { | 616 | { |
@@ -337,6 +619,7 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
337 | u8 subsys = 0, opcode = 0; | 619 | u8 subsys = 0, opcode = 0; |
338 | int status; | 620 | int status; |
339 | 621 | ||
622 | SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_q_destroy \n"); | ||
340 | spin_lock(&ctrl->mbox_lock); | 623 | spin_lock(&ctrl->mbox_lock); |
341 | memset(wrb, 0, sizeof(*wrb)); | 624 | memset(wrb, 0, sizeof(*wrb)); |
342 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 625 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
@@ -350,6 +633,10 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
350 | subsys = CMD_SUBSYSTEM_COMMON; | 633 | subsys = CMD_SUBSYSTEM_COMMON; |
351 | opcode = OPCODE_COMMON_CQ_DESTROY; | 634 | opcode = OPCODE_COMMON_CQ_DESTROY; |
352 | break; | 635 | break; |
636 | case QTYPE_MCCQ: | ||
637 | subsys = CMD_SUBSYSTEM_COMMON; | ||
638 | opcode = OPCODE_COMMON_MCC_DESTROY; | ||
639 | break; | ||
353 | case QTYPE_WRBQ: | 640 | case QTYPE_WRBQ: |
354 | subsys = CMD_SUBSYSTEM_ISCSI; | 641 | subsys = CMD_SUBSYSTEM_ISCSI; |
355 | opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY; | 642 | opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY; |
@@ -377,30 +664,6 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
377 | return status; | 664 | return status; |
378 | } | 665 | } |
379 | 666 | ||
380 | int 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 | |||
404 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | 667 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, |
405 | struct be_queue_info *cq, | 668 | struct be_queue_info *cq, |
406 | struct be_queue_info *dq, int length, | 669 | struct be_queue_info *dq, int length, |
@@ -412,6 +675,7 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | |||
412 | void *ctxt = &req->context; | 675 | void *ctxt = &req->context; |
413 | int status; | 676 | int status; |
414 | 677 | ||
678 | SE_DEBUG(DBG_LVL_8, "In be_cmd_create_default_pdu_queue\n"); | ||
415 | spin_lock(&ctrl->mbox_lock); | 679 | spin_lock(&ctrl->mbox_lock); |
416 | memset(wrb, 0, sizeof(*wrb)); | 680 | memset(wrb, 0, sizeof(*wrb)); |
417 | 681 | ||
@@ -468,8 +732,10 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | |||
468 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 732 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); |
469 | 733 | ||
470 | status = be_mbox_notify(ctrl); | 734 | status = be_mbox_notify(ctrl); |
471 | if (!status) | 735 | if (!status) { |
472 | wrbq->id = le16_to_cpu(resp->cid); | 736 | wrbq->id = le16_to_cpu(resp->cid); |
737 | wrbq->created = true; | ||
738 | } | ||
473 | spin_unlock(&ctrl->mbox_lock); | 739 | spin_unlock(&ctrl->mbox_lock); |
474 | return status; | 740 | return status; |
475 | } | 741 | } |
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index c20d686cbb43..49fcc787ee8b 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -47,6 +47,8 @@ struct be_mcc_wrb { | |||
47 | 47 | ||
48 | #define CQE_FLAGS_VALID_MASK (1 << 31) | 48 | #define CQE_FLAGS_VALID_MASK (1 << 31) |
49 | #define CQE_FLAGS_ASYNC_MASK (1 << 30) | 49 | #define CQE_FLAGS_ASYNC_MASK (1 << 30) |
50 | #define CQE_FLAGS_COMPLETED_MASK (1 << 28) | ||
51 | #define CQE_FLAGS_CONSUMED_MASK (1 << 27) | ||
50 | 52 | ||
51 | /* Completion Status */ | 53 | /* Completion Status */ |
52 | #define MCC_STATUS_SUCCESS 0x0 | 54 | #define MCC_STATUS_SUCCESS 0x0 |
@@ -173,7 +175,7 @@ struct be_cmd_req_hdr { | |||
173 | u8 domain; /* dword 0 */ | 175 | u8 domain; /* dword 0 */ |
174 | u32 timeout; /* dword 1 */ | 176 | u32 timeout; /* dword 1 */ |
175 | u32 request_length; /* dword 2 */ | 177 | u32 request_length; /* dword 2 */ |
176 | u32 rsvd; /* dword 3 */ | 178 | u32 rsvd0; /* dword 3 */ |
177 | }; | 179 | }; |
178 | 180 | ||
179 | struct be_cmd_resp_hdr { | 181 | struct be_cmd_resp_hdr { |
@@ -382,7 +384,6 @@ struct be_cmd_req_modify_eq_delay { | |||
382 | 384 | ||
383 | #define ETH_ALEN 6 | 385 | #define ETH_ALEN 6 |
384 | 386 | ||
385 | |||
386 | struct be_cmd_req_get_mac_addr { | 387 | struct be_cmd_req_get_mac_addr { |
387 | struct be_cmd_req_hdr hdr; | 388 | struct be_cmd_req_hdr hdr; |
388 | u32 nic_port_count; | 389 | u32 nic_port_count; |
@@ -417,14 +418,27 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
417 | 418 | ||
418 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | 419 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, |
419 | int type); | 420 | int type); |
420 | int be_poll_mcc(struct be_ctrl_info *ctrl); | 421 | int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, |
421 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl); | 422 | struct be_queue_info *mccq, |
422 | int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr); | 423 | struct be_queue_info *cq); |
423 | 424 | ||
425 | int be_poll_mcc(struct be_ctrl_info *ctrl); | ||
426 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | ||
427 | struct beiscsi_hba *phba); | ||
428 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); | ||
429 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); | ||
424 | /*ISCSI Functuions */ | 430 | /*ISCSI Functuions */ |
425 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | 431 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); |
426 | 432 | ||
427 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); | 433 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); |
434 | struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba); | ||
435 | int be_mcc_notify_wait(struct beiscsi_hba *phba); | ||
436 | void be_mcc_notify(struct beiscsi_hba *phba); | ||
437 | unsigned int alloc_mcc_tag(struct beiscsi_hba *phba); | ||
438 | void beiscsi_async_link_state_process(struct beiscsi_hba *phba, | ||
439 | struct be_async_event_link_state *evt); | ||
440 | int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, | ||
441 | struct be_mcc_compl *compl); | ||
428 | 442 | ||
429 | int be_mbox_notify(struct be_ctrl_info *ctrl); | 443 | int be_mbox_notify(struct be_ctrl_info *ctrl); |
430 | 444 | ||
@@ -440,6 +454,8 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | |||
440 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | 454 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, |
441 | struct be_queue_info *wrbq); | 455 | struct be_queue_info *wrbq); |
442 | 456 | ||
457 | bool is_link_state_evt(u32 trailer); | ||
458 | |||
443 | struct be_default_pdu_context { | 459 | struct be_default_pdu_context { |
444 | u32 dw[4]; | 460 | u32 dw[4]; |
445 | } __packed; | 461 | } __packed; |
@@ -531,6 +547,23 @@ struct amap_sol_cqe { | |||
531 | u8 valid; /* dword 3 */ | 547 | u8 valid; /* dword 3 */ |
532 | } __packed; | 548 | } __packed; |
533 | 549 | ||
550 | #define SOL_ICD_INDEX_MASK 0x0003FFC0 | ||
551 | struct amap_sol_cqe_ring { | ||
552 | u8 hw_sts[8]; /* dword 0 */ | ||
553 | u8 i_sts[8]; /* dword 0 */ | ||
554 | u8 i_resp[8]; /* dword 0 */ | ||
555 | u8 i_flags[7]; /* dword 0 */ | ||
556 | u8 s; /* dword 0 */ | ||
557 | u8 i_exp_cmd_sn[32]; /* dword 1 */ | ||
558 | u8 code[6]; /* dword 2 */ | ||
559 | u8 icd_index[12]; /* dword 2 */ | ||
560 | u8 rsvd[6]; /* dword 2 */ | ||
561 | u8 i_cmd_wnd[8]; /* dword 2 */ | ||
562 | u8 i_res_cnt[31]; /* dword 3 */ | ||
563 | u8 valid; /* dword 3 */ | ||
564 | } __packed; | ||
565 | |||
566 | |||
534 | 567 | ||
535 | /** | 568 | /** |
536 | * Post WRB Queue Doorbell Register used by the host Storage | 569 | * Post WRB Queue Doorbell Register used by the host Storage |
@@ -664,8 +697,8 @@ struct be_fw_cfg { | |||
664 | #define OPCODE_COMMON_TCP_UPLOAD 56 | 697 | #define OPCODE_COMMON_TCP_UPLOAD 56 |
665 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 | 698 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 |
666 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | 699 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ |
667 | #define CMD_ISCSI_CONNECTION_INVALIDATE 1 | 700 | #define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 |
668 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2 | 701 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 |
669 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 | 702 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 |
670 | 703 | ||
671 | #define INI_WR_CMD 1 /* Initiator write command */ | 704 | #define INI_WR_CMD 1 /* Initiator write command */ |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 2fd25442cfaf..c3928cb8b042 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -67,11 +67,11 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | |||
67 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; | 67 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; |
68 | } | 68 | } |
69 | 69 | ||
70 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, | 70 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, |
71 | shost, cmds_max, | 71 | shost, cmds_max, |
72 | sizeof(*beiscsi_sess), | 72 | sizeof(*beiscsi_sess), |
73 | sizeof(*io_task), | 73 | sizeof(*io_task), |
74 | initial_cmdsn, ISCSI_MAX_TARGET); | 74 | initial_cmdsn, ISCSI_MAX_TARGET); |
75 | if (!cls_session) | 75 | if (!cls_session) |
76 | return NULL; | 76 | return NULL; |
77 | sess = cls_session->dd_data; | 77 | sess = cls_session->dd_data; |
@@ -101,6 +101,7 @@ void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) | |||
101 | struct iscsi_session *sess = cls_session->dd_data; | 101 | struct iscsi_session *sess = cls_session->dd_data; |
102 | struct beiscsi_session *beiscsi_sess = sess->dd_data; | 102 | struct beiscsi_session *beiscsi_sess = sess->dd_data; |
103 | 103 | ||
104 | SE_DEBUG(DBG_LVL_8, "In beiscsi_session_destroy\n"); | ||
104 | pci_pool_destroy(beiscsi_sess->bhs_pool); | 105 | pci_pool_destroy(beiscsi_sess->bhs_pool); |
105 | iscsi_session_teardown(cls_session); | 106 | iscsi_session_teardown(cls_session); |
106 | } | 107 | } |
@@ -224,6 +225,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
224 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 225 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
225 | int len = 0; | 226 | int len = 0; |
226 | 227 | ||
228 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param); | ||
227 | beiscsi_ep = beiscsi_conn->ep; | 229 | beiscsi_ep = beiscsi_conn->ep; |
228 | if (!beiscsi_ep) { | 230 | if (!beiscsi_ep) { |
229 | SE_DEBUG(DBG_LVL_1, | 231 | SE_DEBUG(DBG_LVL_1, |
@@ -254,6 +256,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
254 | struct iscsi_session *session = conn->session; | 256 | struct iscsi_session *session = conn->session; |
255 | int ret; | 257 | int ret; |
256 | 258 | ||
259 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_set_param, param= %d\n", param); | ||
257 | ret = iscsi_set_param(cls_conn, param, buf, buflen); | 260 | ret = iscsi_set_param(cls_conn, param, buf, buflen); |
258 | if (ret) | 261 | if (ret) |
259 | return ret; | 262 | return ret; |
@@ -271,8 +274,8 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
271 | conn->max_recv_dlength = 65536; | 274 | conn->max_recv_dlength = 65536; |
272 | break; | 275 | break; |
273 | case ISCSI_PARAM_MAX_BURST: | 276 | case ISCSI_PARAM_MAX_BURST: |
274 | if (session->first_burst > 262144) | 277 | if (session->max_burst > 262144) |
275 | session->first_burst = 262144; | 278 | session->max_burst = 262144; |
276 | break; | 279 | break; |
277 | default: | 280 | default: |
278 | return 0; | 281 | return 0; |
@@ -293,12 +296,41 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
293 | enum iscsi_host_param param, char *buf) | 296 | enum iscsi_host_param param, char *buf) |
294 | { | 297 | { |
295 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 298 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); |
299 | struct be_cmd_resp_get_mac_addr *resp; | ||
300 | struct be_mcc_wrb *wrb; | ||
301 | unsigned int tag, wrb_num; | ||
296 | int len = 0; | 302 | int len = 0; |
303 | unsigned short status, extd_status; | ||
304 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
297 | 305 | ||
306 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | ||
298 | switch (param) { | 307 | switch (param) { |
299 | case ISCSI_HOST_PARAM_HWADDRESS: | 308 | case ISCSI_HOST_PARAM_HWADDRESS: |
300 | be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address); | 309 | tag = be_cmd_get_mac_addr(phba); |
301 | len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); | 310 | if (!tag) { |
311 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed \n"); | ||
312 | return -1; | ||
313 | } else | ||
314 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
315 | phba->ctrl.mcc_numtag[tag]); | ||
316 | |||
317 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
318 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
319 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
320 | if (status || extd_status) { | ||
321 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
322 | " status = %d extd_status = %d \n", | ||
323 | status, extd_status); | ||
324 | free_mcc_tag(&phba->ctrl, tag); | ||
325 | return -1; | ||
326 | } else { | ||
327 | wrb = queue_get_wrb(mccq, wrb_num); | ||
328 | free_mcc_tag(&phba->ctrl, tag); | ||
329 | resp = embedded_payload(wrb); | ||
330 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
331 | len = sysfs_format_mac(buf, phba->mac_address, | ||
332 | ETH_ALEN); | ||
333 | } | ||
302 | break; | 334 | break; |
303 | default: | 335 | default: |
304 | return iscsi_host_get_param(shost, param, buf); | 336 | return iscsi_host_get_param(shost, param, buf); |
@@ -377,16 +409,13 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
377 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 409 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
378 | struct beiscsi_endpoint *beiscsi_ep; | 410 | struct beiscsi_endpoint *beiscsi_ep; |
379 | struct beiscsi_offload_params params; | 411 | struct beiscsi_offload_params params; |
380 | struct iscsi_session *session = conn->session; | ||
381 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); | ||
382 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
383 | 412 | ||
413 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_start\n"); | ||
384 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 414 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
385 | beiscsi_ep = beiscsi_conn->ep; | 415 | beiscsi_ep = beiscsi_conn->ep; |
386 | if (!beiscsi_ep) | 416 | if (!beiscsi_ep) |
387 | SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n"); | 417 | SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n"); |
388 | 418 | ||
389 | free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle); | ||
390 | beiscsi_conn->login_in_progress = 0; | 419 | beiscsi_conn->login_in_progress = 0; |
391 | beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); | 420 | beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); |
392 | beiscsi_offload_connection(beiscsi_conn, ¶ms); | 421 | beiscsi_offload_connection(beiscsi_conn, ¶ms); |
@@ -426,8 +455,14 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
426 | { | 455 | { |
427 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 456 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; |
428 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 457 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
458 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
459 | struct be_mcc_wrb *wrb; | ||
460 | struct tcp_connect_and_offload_out *ptcpcnct_out; | ||
461 | unsigned short status, extd_status; | ||
462 | unsigned int tag, wrb_num; | ||
429 | int ret = -1; | 463 | int ret = -1; |
430 | 464 | ||
465 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n"); | ||
431 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); | 466 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); |
432 | if (beiscsi_ep->ep_cid == 0xFFFF) { | 467 | if (beiscsi_ep->ep_cid == 0xFFFF) { |
433 | SE_DEBUG(DBG_LVL_1, "No free cid available\n"); | 468 | SE_DEBUG(DBG_LVL_1, "No free cid available\n"); |
@@ -435,15 +470,44 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
435 | } | 470 | } |
436 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", | 471 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", |
437 | beiscsi_ep->ep_cid); | 472 | beiscsi_ep->ep_cid); |
438 | phba->ep_array[beiscsi_ep->ep_cid] = ep; | 473 | phba->ep_array[beiscsi_ep->ep_cid - |
439 | if (beiscsi_ep->ep_cid > | 474 | phba->fw_config.iscsi_cid_start] = ep; |
440 | (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) { | 475 | if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + |
476 | phba->params.cxns_per_ctrl * 2)) { | ||
441 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | 477 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); |
442 | return ret; | 478 | return ret; |
443 | } | 479 | } |
444 | 480 | ||
445 | beiscsi_ep->cid_vld = 0; | 481 | beiscsi_ep->cid_vld = 0; |
446 | return mgmt_open_connection(phba, dst_addr, beiscsi_ep); | 482 | tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); |
483 | if (!tag) { | ||
484 | SE_DEBUG(DBG_LVL_1, | ||
485 | "mgmt_open_connection Failed for cid=%d \n", | ||
486 | beiscsi_ep->ep_cid); | ||
487 | } else { | ||
488 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
489 | phba->ctrl.mcc_numtag[tag]); | ||
490 | } | ||
491 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
492 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
493 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
494 | if (status || extd_status) { | ||
495 | SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" | ||
496 | " status = %d extd_status = %d \n", | ||
497 | status, extd_status); | ||
498 | free_mcc_tag(&phba->ctrl, tag); | ||
499 | return -1; | ||
500 | } else { | ||
501 | wrb = queue_get_wrb(mccq, wrb_num); | ||
502 | free_mcc_tag(&phba->ctrl, tag); | ||
503 | |||
504 | ptcpcnct_out = embedded_payload(wrb); | ||
505 | beiscsi_ep = ep->dd_data; | ||
506 | beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; | ||
507 | beiscsi_ep->cid_vld = 1; | ||
508 | SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); | ||
509 | } | ||
510 | return 0; | ||
447 | } | 511 | } |
448 | 512 | ||
449 | /** | 513 | /** |
@@ -463,14 +527,12 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | |||
463 | * beiscsi_free_ep - free endpoint | 527 | * beiscsi_free_ep - free endpoint |
464 | * @ep: pointer to iscsi endpoint structure | 528 | * @ep: pointer to iscsi endpoint structure |
465 | */ | 529 | */ |
466 | static void beiscsi_free_ep(struct iscsi_endpoint *ep) | 530 | static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) |
467 | { | 531 | { |
468 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
469 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 532 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
470 | 533 | ||
471 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 534 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); |
472 | beiscsi_ep->phba = NULL; | 535 | beiscsi_ep->phba = NULL; |
473 | iscsi_destroy_endpoint(ep); | ||
474 | } | 536 | } |
475 | 537 | ||
476 | /** | 538 | /** |
@@ -498,6 +560,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
498 | SE_DEBUG(DBG_LVL_1, "shost is NULL \n"); | 560 | SE_DEBUG(DBG_LVL_1, "shost is NULL \n"); |
499 | return ERR_PTR(ret); | 561 | return ERR_PTR(ret); |
500 | } | 562 | } |
563 | |||
564 | if (phba->state != BE_ADAPTER_UP) { | ||
565 | ret = -EBUSY; | ||
566 | SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP \n"); | ||
567 | return ERR_PTR(ret); | ||
568 | } | ||
569 | |||
501 | ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); | 570 | ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); |
502 | if (!ep) { | 571 | if (!ep) { |
503 | ret = -ENOMEM; | 572 | ret = -ENOMEM; |
@@ -506,9 +575,9 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
506 | 575 | ||
507 | beiscsi_ep = ep->dd_data; | 576 | beiscsi_ep = ep->dd_data; |
508 | beiscsi_ep->phba = phba; | 577 | beiscsi_ep->phba = phba; |
509 | 578 | beiscsi_ep->openiscsi_ep = ep; | |
510 | if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { | 579 | if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { |
511 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | 580 | SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n"); |
512 | ret = -ENOMEM; | 581 | ret = -ENOMEM; |
513 | goto free_ep; | 582 | goto free_ep; |
514 | } | 583 | } |
@@ -516,7 +585,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
516 | return ep; | 585 | return ep; |
517 | 586 | ||
518 | free_ep: | 587 | free_ep: |
519 | beiscsi_free_ep(ep); | 588 | beiscsi_free_ep(beiscsi_ep); |
520 | return ERR_PTR(ret); | 589 | return ERR_PTR(ret); |
521 | } | 590 | } |
522 | 591 | ||
@@ -543,20 +612,22 @@ int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) | |||
543 | * @ep: The iscsi endpoint | 612 | * @ep: The iscsi endpoint |
544 | * @flag: The type of connection closure | 613 | * @flag: The type of connection closure |
545 | */ | 614 | */ |
546 | static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag) | 615 | static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) |
547 | { | 616 | { |
548 | int ret = 0; | 617 | int ret = 0; |
549 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 618 | unsigned int tag; |
550 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 619 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
551 | 620 | ||
552 | if (MGMT_STATUS_SUCCESS != | 621 | tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); |
553 | mgmt_upload_connection(phba, beiscsi_ep->ep_cid, | 622 | if (!tag) { |
554 | CONNECTION_UPLOAD_GRACEFUL)) { | ||
555 | SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", | 623 | SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", |
556 | beiscsi_ep->ep_cid); | 624 | beiscsi_ep->ep_cid); |
557 | ret = -1; | 625 | ret = -1; |
626 | } else { | ||
627 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
628 | phba->ctrl.mcc_numtag[tag]); | ||
629 | free_mcc_tag(&phba->ctrl, tag); | ||
558 | } | 630 | } |
559 | |||
560 | return ret; | 631 | return ret; |
561 | } | 632 | } |
562 | 633 | ||
@@ -571,19 +642,17 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
571 | struct beiscsi_conn *beiscsi_conn; | 642 | struct beiscsi_conn *beiscsi_conn; |
572 | struct beiscsi_endpoint *beiscsi_ep; | 643 | struct beiscsi_endpoint *beiscsi_ep; |
573 | struct beiscsi_hba *phba; | 644 | struct beiscsi_hba *phba; |
574 | int flag = 0; | ||
575 | 645 | ||
576 | beiscsi_ep = ep->dd_data; | 646 | beiscsi_ep = ep->dd_data; |
577 | phba = beiscsi_ep->phba; | 647 | phba = beiscsi_ep->phba; |
578 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n"); | 648 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n", |
649 | beiscsi_ep->ep_cid); | ||
579 | 650 | ||
580 | if (beiscsi_ep->conn) { | 651 | if (beiscsi_ep->conn) { |
581 | beiscsi_conn = beiscsi_ep->conn; | 652 | beiscsi_conn = beiscsi_ep->conn; |
582 | iscsi_suspend_queue(beiscsi_conn->conn); | 653 | iscsi_suspend_queue(beiscsi_conn->conn); |
583 | beiscsi_close_conn(ep, flag); | ||
584 | } | 654 | } |
585 | 655 | ||
586 | beiscsi_free_ep(ep); | ||
587 | } | 656 | } |
588 | 657 | ||
589 | /** | 658 | /** |
@@ -616,23 +685,31 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | |||
616 | struct iscsi_session *session = conn->session; | 685 | struct iscsi_session *session = conn->session; |
617 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); | 686 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); |
618 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 687 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
619 | unsigned int status; | 688 | unsigned int tag; |
620 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; | 689 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; |
621 | 690 | ||
622 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n"); | ||
623 | beiscsi_ep = beiscsi_conn->ep; | 691 | beiscsi_ep = beiscsi_conn->ep; |
624 | if (!beiscsi_ep) { | 692 | if (!beiscsi_ep) { |
625 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); | 693 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); |
626 | return; | 694 | return; |
627 | } | 695 | } |
628 | status = mgmt_invalidate_connection(phba, beiscsi_ep, | 696 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop ep_cid = %d\n", |
697 | beiscsi_ep->ep_cid); | ||
698 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, | ||
629 | beiscsi_ep->ep_cid, 1, | 699 | beiscsi_ep->ep_cid, 1, |
630 | savecfg_flag); | 700 | savecfg_flag); |
631 | if (status != MGMT_STATUS_SUCCESS) { | 701 | if (!tag) { |
632 | SE_DEBUG(DBG_LVL_1, | 702 | SE_DEBUG(DBG_LVL_1, |
633 | "mgmt_invalidate_connection Failed for cid=%d \n", | 703 | "mgmt_invalidate_connection Failed for cid=%d \n", |
634 | beiscsi_ep->ep_cid); | 704 | beiscsi_ep->ep_cid); |
705 | } else { | ||
706 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
707 | phba->ctrl.mcc_numtag[tag]); | ||
708 | free_mcc_tag(&phba->ctrl, tag); | ||
635 | } | 709 | } |
710 | beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL); | ||
711 | beiscsi_free_ep(beiscsi_ep); | ||
712 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | ||
636 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | 713 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); |
637 | iscsi_conn_stop(cls_conn, flag); | 714 | iscsi_conn_stop(cls_conn, flag); |
638 | } | 715 | } |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index f92ffc5349fb..1f512c28cbf9 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 4f1aca346e38..dd5b105f8f47 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
@@ -39,7 +40,7 @@ | |||
39 | 40 | ||
40 | static unsigned int be_iopoll_budget = 10; | 41 | static unsigned int be_iopoll_budget = 10; |
41 | static unsigned int be_max_phys_size = 64; | 42 | static unsigned int be_max_phys_size = 64; |
42 | static unsigned int enable_msix; | 43 | static unsigned int enable_msix = 1; |
43 | 44 | ||
44 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); | 45 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); |
45 | MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); | 46 | MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); |
@@ -58,17 +59,145 @@ static int beiscsi_slave_configure(struct scsi_device *sdev) | |||
58 | return 0; | 59 | return 0; |
59 | } | 60 | } |
60 | 61 | ||
62 | static int beiscsi_eh_abort(struct scsi_cmnd *sc) | ||
63 | { | ||
64 | struct iscsi_cls_session *cls_session; | ||
65 | struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; | ||
66 | struct beiscsi_io_task *aborted_io_task; | ||
67 | struct iscsi_conn *conn; | ||
68 | struct beiscsi_conn *beiscsi_conn; | ||
69 | struct beiscsi_hba *phba; | ||
70 | struct iscsi_session *session; | ||
71 | struct invalidate_command_table *inv_tbl; | ||
72 | unsigned int cid, tag, num_invalidate; | ||
73 | |||
74 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
75 | session = cls_session->dd_data; | ||
76 | |||
77 | spin_lock_bh(&session->lock); | ||
78 | if (!aborted_task || !aborted_task->sc) { | ||
79 | /* we raced */ | ||
80 | spin_unlock_bh(&session->lock); | ||
81 | return SUCCESS; | ||
82 | } | ||
83 | |||
84 | aborted_io_task = aborted_task->dd_data; | ||
85 | if (!aborted_io_task->scsi_cmnd) { | ||
86 | /* raced or invalid command */ | ||
87 | spin_unlock_bh(&session->lock); | ||
88 | return SUCCESS; | ||
89 | } | ||
90 | spin_unlock_bh(&session->lock); | ||
91 | conn = aborted_task->conn; | ||
92 | beiscsi_conn = conn->dd_data; | ||
93 | phba = beiscsi_conn->phba; | ||
94 | |||
95 | /* invalidate iocb */ | ||
96 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
97 | inv_tbl = phba->inv_tbl; | ||
98 | memset(inv_tbl, 0x0, sizeof(*inv_tbl)); | ||
99 | inv_tbl->cid = cid; | ||
100 | inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; | ||
101 | num_invalidate = 1; | ||
102 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
103 | if (!tag) { | ||
104 | shost_printk(KERN_WARNING, phba->shost, | ||
105 | "mgmt_invalidate_icds could not be" | ||
106 | " submitted\n"); | ||
107 | return FAILED; | ||
108 | } else { | ||
109 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
110 | phba->ctrl.mcc_numtag[tag]); | ||
111 | free_mcc_tag(&phba->ctrl, tag); | ||
112 | } | ||
113 | |||
114 | return iscsi_eh_abort(sc); | ||
115 | } | ||
116 | |||
117 | static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) | ||
118 | { | ||
119 | struct iscsi_task *abrt_task; | ||
120 | struct beiscsi_io_task *abrt_io_task; | ||
121 | struct iscsi_conn *conn; | ||
122 | struct beiscsi_conn *beiscsi_conn; | ||
123 | struct beiscsi_hba *phba; | ||
124 | struct iscsi_session *session; | ||
125 | struct iscsi_cls_session *cls_session; | ||
126 | struct invalidate_command_table *inv_tbl; | ||
127 | unsigned int cid, tag, i, num_invalidate; | ||
128 | int rc = FAILED; | ||
129 | |||
130 | /* invalidate iocbs */ | ||
131 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
132 | session = cls_session->dd_data; | ||
133 | spin_lock_bh(&session->lock); | ||
134 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) | ||
135 | goto unlock; | ||
136 | |||
137 | conn = session->leadconn; | ||
138 | beiscsi_conn = conn->dd_data; | ||
139 | phba = beiscsi_conn->phba; | ||
140 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
141 | inv_tbl = phba->inv_tbl; | ||
142 | memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN); | ||
143 | num_invalidate = 0; | ||
144 | for (i = 0; i < conn->session->cmds_max; i++) { | ||
145 | abrt_task = conn->session->cmds[i]; | ||
146 | abrt_io_task = abrt_task->dd_data; | ||
147 | if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE) | ||
148 | continue; | ||
149 | |||
150 | if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) | ||
151 | continue; | ||
152 | |||
153 | inv_tbl->cid = cid; | ||
154 | inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; | ||
155 | num_invalidate++; | ||
156 | inv_tbl++; | ||
157 | } | ||
158 | spin_unlock_bh(&session->lock); | ||
159 | inv_tbl = phba->inv_tbl; | ||
160 | |||
161 | tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); | ||
162 | if (!tag) { | ||
163 | shost_printk(KERN_WARNING, phba->shost, | ||
164 | "mgmt_invalidate_icds could not be" | ||
165 | " submitted\n"); | ||
166 | return FAILED; | ||
167 | } else { | ||
168 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
169 | phba->ctrl.mcc_numtag[tag]); | ||
170 | free_mcc_tag(&phba->ctrl, tag); | ||
171 | } | ||
172 | |||
173 | return iscsi_eh_device_reset(sc); | ||
174 | unlock: | ||
175 | spin_unlock_bh(&session->lock); | ||
176 | return rc; | ||
177 | } | ||
178 | |||
179 | /*------------------- PCI Driver operations and data ----------------- */ | ||
180 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | ||
181 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | ||
182 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, | ||
183 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, | ||
184 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, | ||
185 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, | ||
186 | { 0 } | ||
187 | }; | ||
188 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); | ||
189 | |||
61 | static struct scsi_host_template beiscsi_sht = { | 190 | static struct scsi_host_template beiscsi_sht = { |
62 | .module = THIS_MODULE, | 191 | .module = THIS_MODULE, |
63 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", | 192 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", |
64 | .proc_name = DRV_NAME, | 193 | .proc_name = DRV_NAME, |
65 | .queuecommand = iscsi_queuecommand, | 194 | .queuecommand = iscsi_queuecommand, |
66 | .eh_abort_handler = iscsi_eh_abort, | ||
67 | .change_queue_depth = iscsi_change_queue_depth, | 195 | .change_queue_depth = iscsi_change_queue_depth, |
68 | .slave_configure = beiscsi_slave_configure, | 196 | .slave_configure = beiscsi_slave_configure, |
69 | .target_alloc = iscsi_target_alloc, | 197 | .target_alloc = iscsi_target_alloc, |
70 | .eh_device_reset_handler = iscsi_eh_device_reset, | 198 | .eh_abort_handler = beiscsi_eh_abort, |
71 | .eh_target_reset_handler = iscsi_eh_target_reset, | 199 | .eh_device_reset_handler = beiscsi_eh_device_reset, |
200 | .eh_target_reset_handler = iscsi_eh_session_reset, | ||
72 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, | 201 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, |
73 | .can_queue = BE2_IO_DEPTH, | 202 | .can_queue = BE2_IO_DEPTH, |
74 | .this_id = -1, | 203 | .this_id = -1, |
@@ -76,16 +205,8 @@ static struct scsi_host_template beiscsi_sht = { | |||
76 | .cmd_per_lun = BEISCSI_CMD_PER_LUN, | 205 | .cmd_per_lun = BEISCSI_CMD_PER_LUN, |
77 | .use_clustering = ENABLE_CLUSTERING, | 206 | .use_clustering = ENABLE_CLUSTERING, |
78 | }; | 207 | }; |
79 | static struct scsi_transport_template *beiscsi_scsi_transport; | ||
80 | 208 | ||
81 | /*------------------- PCI Driver operations and data ----------------- */ | 209 | static struct scsi_transport_template *beiscsi_scsi_transport; |
82 | static 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 | }; | ||
88 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); | ||
89 | 210 | ||
90 | static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | 211 | static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) |
91 | { | 212 | { |
@@ -104,11 +225,11 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | |||
104 | shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; | 225 | shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; |
105 | shost->max_lun = BEISCSI_NUM_MAX_LUN; | 226 | shost->max_lun = BEISCSI_NUM_MAX_LUN; |
106 | shost->transportt = beiscsi_scsi_transport; | 227 | shost->transportt = beiscsi_scsi_transport; |
107 | |||
108 | phba = iscsi_host_priv(shost); | 228 | phba = iscsi_host_priv(shost); |
109 | memset(phba, 0, sizeof(*phba)); | 229 | memset(phba, 0, sizeof(*phba)); |
110 | phba->shost = shost; | 230 | phba->shost = shost; |
111 | phba->pcidev = pci_dev_get(pcidev); | 231 | phba->pcidev = pci_dev_get(pcidev); |
232 | pci_set_drvdata(pcidev, phba); | ||
112 | 233 | ||
113 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | 234 | if (iscsi_host_add(shost, &phba->pcidev->dev)) |
114 | goto free_devices; | 235 | goto free_devices; |
@@ -140,6 +261,7 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, | |||
140 | struct pci_dev *pcidev) | 261 | struct pci_dev *pcidev) |
141 | { | 262 | { |
142 | u8 __iomem *addr; | 263 | u8 __iomem *addr; |
264 | int pcicfg_reg; | ||
143 | 265 | ||
144 | addr = ioremap_nocache(pci_resource_start(pcidev, 2), | 266 | addr = ioremap_nocache(pci_resource_start(pcidev, 2), |
145 | pci_resource_len(pcidev, 2)); | 267 | pci_resource_len(pcidev, 2)); |
@@ -156,13 +278,19 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, | |||
156 | phba->db_va = addr; | 278 | phba->db_va = addr; |
157 | phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4); | 279 | phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4); |
158 | 280 | ||
159 | addr = ioremap_nocache(pci_resource_start(pcidev, 1), | 281 | if (phba->generation == BE_GEN2) |
160 | pci_resource_len(pcidev, 1)); | 282 | pcicfg_reg = 1; |
283 | else | ||
284 | pcicfg_reg = 0; | ||
285 | |||
286 | addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg), | ||
287 | pci_resource_len(pcidev, pcicfg_reg)); | ||
288 | |||
161 | if (addr == NULL) | 289 | if (addr == NULL) |
162 | goto pci_map_err; | 290 | goto pci_map_err; |
163 | phba->ctrl.pcicfg = addr; | 291 | phba->ctrl.pcicfg = addr; |
164 | phba->pci_va = addr; | 292 | phba->pci_va = addr; |
165 | phba->pci_pa.u.a64.address = pci_resource_start(pcidev, 1); | 293 | phba->pci_pa.u.a64.address = pci_resource_start(pcidev, pcicfg_reg); |
166 | return 0; | 294 | return 0; |
167 | 295 | ||
168 | pci_map_err: | 296 | pci_map_err: |
@@ -181,6 +309,7 @@ static int beiscsi_enable_pci(struct pci_dev *pcidev) | |||
181 | return ret; | 309 | return ret; |
182 | } | 310 | } |
183 | 311 | ||
312 | pci_set_master(pcidev); | ||
184 | if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) { | 313 | if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) { |
185 | ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)); | 314 | ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)); |
186 | if (ret) { | 315 | if (ret) { |
@@ -203,7 +332,6 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) | |||
203 | status = beiscsi_map_pci_bars(phba, pdev); | 332 | status = beiscsi_map_pci_bars(phba, pdev); |
204 | if (status) | 333 | if (status) |
205 | return status; | 334 | return status; |
206 | |||
207 | mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; | 335 | mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; |
208 | mbox_mem_alloc->va = pci_alloc_consistent(pdev, | 336 | mbox_mem_alloc->va = pci_alloc_consistent(pdev, |
209 | mbox_mem_alloc->size, | 337 | mbox_mem_alloc->size, |
@@ -219,34 +347,35 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) | |||
219 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); | 347 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); |
220 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); | 348 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); |
221 | spin_lock_init(&ctrl->mbox_lock); | 349 | spin_lock_init(&ctrl->mbox_lock); |
350 | spin_lock_init(&phba->ctrl.mcc_lock); | ||
351 | spin_lock_init(&phba->ctrl.mcc_cq_lock); | ||
352 | |||
222 | return status; | 353 | return status; |
223 | } | 354 | } |
224 | 355 | ||
225 | static void beiscsi_get_params(struct beiscsi_hba *phba) | 356 | static void beiscsi_get_params(struct beiscsi_hba *phba) |
226 | { | 357 | { |
227 | phba->params.ios_per_ctrl = BE2_IO_DEPTH; | 358 | phba->params.ios_per_ctrl = (phba->fw_config.iscsi_icd_count |
228 | phba->params.cxns_per_ctrl = BE2_MAX_SESSIONS; | 359 | - (phba->fw_config.iscsi_cid_count |
229 | phba->params.asyncpdus_per_ctrl = BE2_ASYNCPDUS; | 360 | + BE2_TMFS |
230 | phba->params.icds_per_ctrl = BE2_MAX_ICDS / 2; | 361 | + BE2_NOPOUT_REQ)); |
362 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; | ||
363 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2; | ||
364 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;; | ||
231 | phba->params.num_sge_per_io = BE2_SGE; | 365 | phba->params.num_sge_per_io = BE2_SGE; |
232 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; | 366 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; |
233 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; | 367 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; |
234 | phba->params.eq_timer = 64; | 368 | phba->params.eq_timer = 64; |
235 | phba->params.num_eq_entries = | 369 | phba->params.num_eq_entries = |
236 | (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) / | 370 | (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 |
237 | 512) + 1) * 512; | 371 | + BE2_TMFS) / 512) + 1) * 512; |
238 | phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) | 372 | phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) |
239 | ? 1024 : phba->params.num_eq_entries; | 373 | ? 1024 : phba->params.num_eq_entries; |
240 | SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n", | 374 | SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n", |
241 | phba->params.num_eq_entries); | 375 | phba->params.num_eq_entries); |
242 | phba->params.num_cq_entries = | 376 | phba->params.num_cq_entries = |
243 | (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) / | 377 | (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 |
244 | 512) + 1) * 512; | 378 | + BE2_TMFS) / 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; | 379 | phba->params.wrbs_per_cxn = 256; |
251 | } | 380 | } |
252 | 381 | ||
@@ -268,6 +397,113 @@ static void hwi_ring_eq_db(struct beiscsi_hba *phba, | |||
268 | } | 397 | } |
269 | 398 | ||
270 | /** | 399 | /** |
400 | * be_isr_mcc - The isr routine of the driver. | ||
401 | * @irq: Not used | ||
402 | * @dev_id: Pointer to host adapter structure | ||
403 | */ | ||
404 | static irqreturn_t be_isr_mcc(int irq, void *dev_id) | ||
405 | { | ||
406 | struct beiscsi_hba *phba; | ||
407 | struct be_eq_entry *eqe = NULL; | ||
408 | struct be_queue_info *eq; | ||
409 | struct be_queue_info *mcc; | ||
410 | unsigned int num_eq_processed; | ||
411 | struct be_eq_obj *pbe_eq; | ||
412 | unsigned long flags; | ||
413 | |||
414 | pbe_eq = dev_id; | ||
415 | eq = &pbe_eq->q; | ||
416 | phba = pbe_eq->phba; | ||
417 | mcc = &phba->ctrl.mcc_obj.cq; | ||
418 | eqe = queue_tail_node(eq); | ||
419 | if (!eqe) | ||
420 | SE_DEBUG(DBG_LVL_1, "eqe is NULL\n"); | ||
421 | |||
422 | num_eq_processed = 0; | ||
423 | |||
424 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
425 | & EQE_VALID_MASK) { | ||
426 | if (((eqe->dw[offsetof(struct amap_eq_entry, | ||
427 | resource_id) / 32] & | ||
428 | EQE_RESID_MASK) >> 16) == mcc->id) { | ||
429 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
430 | phba->todo_mcc_cq = 1; | ||
431 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
432 | } | ||
433 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
434 | queue_tail_inc(eq); | ||
435 | eqe = queue_tail_node(eq); | ||
436 | num_eq_processed++; | ||
437 | } | ||
438 | if (phba->todo_mcc_cq) | ||
439 | queue_work(phba->wq, &phba->work_cqs); | ||
440 | if (num_eq_processed) | ||
441 | hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); | ||
442 | |||
443 | return IRQ_HANDLED; | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * be_isr_msix - The isr routine of the driver. | ||
448 | * @irq: Not used | ||
449 | * @dev_id: Pointer to host adapter structure | ||
450 | */ | ||
451 | static irqreturn_t be_isr_msix(int irq, void *dev_id) | ||
452 | { | ||
453 | struct beiscsi_hba *phba; | ||
454 | struct be_eq_entry *eqe = NULL; | ||
455 | struct be_queue_info *eq; | ||
456 | struct be_queue_info *cq; | ||
457 | unsigned int num_eq_processed; | ||
458 | struct be_eq_obj *pbe_eq; | ||
459 | unsigned long flags; | ||
460 | |||
461 | pbe_eq = dev_id; | ||
462 | eq = &pbe_eq->q; | ||
463 | cq = pbe_eq->cq; | ||
464 | eqe = queue_tail_node(eq); | ||
465 | if (!eqe) | ||
466 | SE_DEBUG(DBG_LVL_1, "eqe is NULL\n"); | ||
467 | |||
468 | phba = pbe_eq->phba; | ||
469 | num_eq_processed = 0; | ||
470 | if (blk_iopoll_enabled) { | ||
471 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
472 | & EQE_VALID_MASK) { | ||
473 | if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) | ||
474 | blk_iopoll_sched(&pbe_eq->iopoll); | ||
475 | |||
476 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
477 | queue_tail_inc(eq); | ||
478 | eqe = queue_tail_node(eq); | ||
479 | num_eq_processed++; | ||
480 | } | ||
481 | if (num_eq_processed) | ||
482 | hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); | ||
483 | |||
484 | return IRQ_HANDLED; | ||
485 | } else { | ||
486 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
487 | & EQE_VALID_MASK) { | ||
488 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
489 | phba->todo_cq = 1; | ||
490 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
491 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
492 | queue_tail_inc(eq); | ||
493 | eqe = queue_tail_node(eq); | ||
494 | num_eq_processed++; | ||
495 | } | ||
496 | if (phba->todo_cq) | ||
497 | queue_work(phba->wq, &phba->work_cqs); | ||
498 | |||
499 | if (num_eq_processed) | ||
500 | hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); | ||
501 | |||
502 | return IRQ_HANDLED; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | /** | ||
271 | * be_isr - The isr routine of the driver. | 507 | * be_isr - The isr routine of the driver. |
272 | * @irq: Not used | 508 | * @irq: Not used |
273 | * @dev_id: Pointer to host adapter structure | 509 | * @dev_id: Pointer to host adapter structure |
@@ -280,48 +516,70 @@ static irqreturn_t be_isr(int irq, void *dev_id) | |||
280 | struct be_eq_entry *eqe = NULL; | 516 | struct be_eq_entry *eqe = NULL; |
281 | struct be_queue_info *eq; | 517 | struct be_queue_info *eq; |
282 | struct be_queue_info *cq; | 518 | struct be_queue_info *cq; |
519 | struct be_queue_info *mcc; | ||
283 | unsigned long flags, index; | 520 | unsigned long flags, index; |
284 | unsigned int num_eq_processed; | 521 | unsigned int num_mcceq_processed, num_ioeq_processed; |
285 | struct be_ctrl_info *ctrl; | 522 | struct be_ctrl_info *ctrl; |
523 | struct be_eq_obj *pbe_eq; | ||
286 | int isr; | 524 | int isr; |
287 | 525 | ||
288 | phba = dev_id; | 526 | phba = dev_id; |
289 | if (!enable_msix) { | 527 | ctrl = &phba->ctrl;; |
290 | ctrl = &phba->ctrl;; | 528 | isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + |
291 | isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + | 529 | (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE)); |
292 | (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE)); | 530 | if (!isr) |
293 | if (!isr) | 531 | return IRQ_NONE; |
294 | return IRQ_NONE; | ||
295 | } | ||
296 | 532 | ||
297 | phwi_ctrlr = phba->phwi_ctrlr; | 533 | phwi_ctrlr = phba->phwi_ctrlr; |
298 | phwi_context = phwi_ctrlr->phwi_ctxt; | 534 | phwi_context = phwi_ctrlr->phwi_ctxt; |
299 | eq = &phwi_context->be_eq.q; | 535 | pbe_eq = &phwi_context->be_eq[0]; |
300 | cq = &phwi_context->be_cq; | 536 | |
537 | eq = &phwi_context->be_eq[0].q; | ||
538 | mcc = &phba->ctrl.mcc_obj.cq; | ||
301 | index = 0; | 539 | index = 0; |
302 | eqe = queue_tail_node(eq); | 540 | eqe = queue_tail_node(eq); |
303 | if (!eqe) | 541 | if (!eqe) |
304 | SE_DEBUG(DBG_LVL_1, "eqe is NULL\n"); | 542 | SE_DEBUG(DBG_LVL_1, "eqe is NULL\n"); |
305 | 543 | ||
306 | num_eq_processed = 0; | 544 | num_ioeq_processed = 0; |
545 | num_mcceq_processed = 0; | ||
307 | if (blk_iopoll_enabled) { | 546 | if (blk_iopoll_enabled) { |
308 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 547 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
309 | & EQE_VALID_MASK) { | 548 | & EQE_VALID_MASK) { |
310 | if (!blk_iopoll_sched_prep(&phba->iopoll)) | 549 | if (((eqe->dw[offsetof(struct amap_eq_entry, |
311 | blk_iopoll_sched(&phba->iopoll); | 550 | resource_id) / 32] & |
312 | 551 | EQE_RESID_MASK) >> 16) == mcc->id) { | |
552 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
553 | phba->todo_mcc_cq = 1; | ||
554 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
555 | num_mcceq_processed++; | ||
556 | } else { | ||
557 | if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) | ||
558 | blk_iopoll_sched(&pbe_eq->iopoll); | ||
559 | num_ioeq_processed++; | ||
560 | } | ||
313 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 561 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
314 | queue_tail_inc(eq); | 562 | queue_tail_inc(eq); |
315 | eqe = queue_tail_node(eq); | 563 | eqe = queue_tail_node(eq); |
316 | num_eq_processed++; | ||
317 | SE_DEBUG(DBG_LVL_8, "Valid EQE\n"); | ||
318 | } | 564 | } |
319 | if (num_eq_processed) { | 565 | if (num_ioeq_processed || num_mcceq_processed) { |
320 | hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 0, 1); | 566 | if (phba->todo_mcc_cq) |
567 | queue_work(phba->wq, &phba->work_cqs); | ||
568 | |||
569 | if ((num_mcceq_processed) && (!num_ioeq_processed)) | ||
570 | hwi_ring_eq_db(phba, eq->id, 0, | ||
571 | (num_ioeq_processed + | ||
572 | num_mcceq_processed) , 1, 1); | ||
573 | else | ||
574 | hwi_ring_eq_db(phba, eq->id, 0, | ||
575 | (num_ioeq_processed + | ||
576 | num_mcceq_processed), 0, 1); | ||
577 | |||
321 | return IRQ_HANDLED; | 578 | return IRQ_HANDLED; |
322 | } else | 579 | } else |
323 | return IRQ_NONE; | 580 | return IRQ_NONE; |
324 | } else { | 581 | } else { |
582 | cq = &phwi_context->be_cq[0]; | ||
325 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 583 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
326 | & EQE_VALID_MASK) { | 584 | & EQE_VALID_MASK) { |
327 | 585 | ||
@@ -339,13 +597,14 @@ static irqreturn_t be_isr(int irq, void *dev_id) | |||
339 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 597 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
340 | queue_tail_inc(eq); | 598 | queue_tail_inc(eq); |
341 | eqe = queue_tail_node(eq); | 599 | eqe = queue_tail_node(eq); |
342 | num_eq_processed++; | 600 | num_ioeq_processed++; |
343 | } | 601 | } |
344 | if (phba->todo_cq || phba->todo_mcc_cq) | 602 | if (phba->todo_cq || phba->todo_mcc_cq) |
345 | queue_work(phba->wq, &phba->work_cqs); | 603 | queue_work(phba->wq, &phba->work_cqs); |
346 | 604 | ||
347 | if (num_eq_processed) { | 605 | if (num_ioeq_processed) { |
348 | hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 1, 1); | 606 | hwi_ring_eq_db(phba, eq->id, 0, |
607 | num_ioeq_processed, 1, 1); | ||
349 | return IRQ_HANDLED; | 608 | return IRQ_HANDLED; |
350 | } else | 609 | } else |
351 | return IRQ_NONE; | 610 | return IRQ_NONE; |
@@ -355,13 +614,32 @@ static irqreturn_t be_isr(int irq, void *dev_id) | |||
355 | static int beiscsi_init_irqs(struct beiscsi_hba *phba) | 614 | static int beiscsi_init_irqs(struct beiscsi_hba *phba) |
356 | { | 615 | { |
357 | struct pci_dev *pcidev = phba->pcidev; | 616 | struct pci_dev *pcidev = phba->pcidev; |
358 | int ret; | 617 | struct hwi_controller *phwi_ctrlr; |
618 | struct hwi_context_memory *phwi_context; | ||
619 | int ret, msix_vec, i = 0; | ||
620 | char desc[32]; | ||
359 | 621 | ||
360 | ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba); | 622 | phwi_ctrlr = phba->phwi_ctrlr; |
361 | if (ret) { | 623 | phwi_context = phwi_ctrlr->phwi_ctxt; |
362 | shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" | 624 | |
363 | "Failed to register irq\\n"); | 625 | if (phba->msix_enabled) { |
364 | return ret; | 626 | for (i = 0; i < phba->num_cpus; i++) { |
627 | sprintf(desc, "beiscsi_msix_%04x", i); | ||
628 | msix_vec = phba->msix_entries[i].vector; | ||
629 | ret = request_irq(msix_vec, be_isr_msix, 0, desc, | ||
630 | &phwi_context->be_eq[i]); | ||
631 | } | ||
632 | msix_vec = phba->msix_entries[i].vector; | ||
633 | ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc", | ||
634 | &phwi_context->be_eq[i]); | ||
635 | } else { | ||
636 | ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, | ||
637 | "beiscsi", phba); | ||
638 | if (ret) { | ||
639 | shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" | ||
640 | "Failed to register irq\\n"); | ||
641 | return ret; | ||
642 | } | ||
365 | } | 643 | } |
366 | return 0; | 644 | return 0; |
367 | } | 645 | } |
@@ -378,15 +656,6 @@ static void hwi_ring_cq_db(struct beiscsi_hba *phba, | |||
378 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); | 656 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); |
379 | } | 657 | } |
380 | 658 | ||
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 | */ | ||
390 | static unsigned int | 659 | static unsigned int |
391 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | 660 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, |
392 | struct beiscsi_hba *phba, | 661 | struct beiscsi_hba *phba, |
@@ -397,6 +666,9 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | |||
397 | { | 666 | { |
398 | struct iscsi_conn *conn = beiscsi_conn->conn; | 667 | struct iscsi_conn *conn = beiscsi_conn->conn; |
399 | struct iscsi_session *session = conn->session; | 668 | struct iscsi_session *session = conn->session; |
669 | struct iscsi_task *task; | ||
670 | struct beiscsi_io_task *io_task; | ||
671 | struct iscsi_hdr *login_hdr; | ||
400 | 672 | ||
401 | switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] & | 673 | switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] & |
402 | PDUBASE_OPCODE_MASK) { | 674 | PDUBASE_OPCODE_MASK) { |
@@ -412,6 +684,11 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | |||
412 | SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n"); | 684 | SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n"); |
413 | break; | 685 | break; |
414 | case ISCSI_OP_LOGIN_RSP: | 686 | case ISCSI_OP_LOGIN_RSP: |
687 | case ISCSI_OP_TEXT_RSP: | ||
688 | task = conn->login_task; | ||
689 | io_task = task->dd_data; | ||
690 | login_hdr = (struct iscsi_hdr *)ppdu; | ||
691 | login_hdr->itt = io_task->libiscsi_itt; | ||
415 | break; | 692 | break; |
416 | default: | 693 | default: |
417 | shost_printk(KERN_WARNING, phba->shost, | 694 | shost_printk(KERN_WARNING, phba->shost, |
@@ -440,7 +717,8 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) | |||
440 | io_sgl_alloc_index]; | 717 | io_sgl_alloc_index]; |
441 | phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL; | 718 | phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL; |
442 | phba->io_sgl_hndl_avbl--; | 719 | phba->io_sgl_hndl_avbl--; |
443 | if (phba->io_sgl_alloc_index == (phba->params.ios_per_ctrl - 1)) | 720 | if (phba->io_sgl_alloc_index == (phba->params. |
721 | ios_per_ctrl - 1)) | ||
444 | phba->io_sgl_alloc_index = 0; | 722 | phba->io_sgl_alloc_index = 0; |
445 | else | 723 | else |
446 | phba->io_sgl_alloc_index++; | 724 | phba->io_sgl_alloc_index++; |
@@ -477,22 +755,31 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) | |||
477 | * alloc_wrb_handle - To allocate a wrb handle | 755 | * alloc_wrb_handle - To allocate a wrb handle |
478 | * @phba: The hba pointer | 756 | * @phba: The hba pointer |
479 | * @cid: The cid to use for allocation | 757 | * @cid: The cid to use for allocation |
480 | * @index: index allocation and wrb index | ||
481 | * | 758 | * |
482 | * This happens under session_lock until submission to chip | 759 | * This happens under session_lock until submission to chip |
483 | */ | 760 | */ |
484 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, | 761 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid) |
485 | int index) | ||
486 | { | 762 | { |
487 | struct hwi_wrb_context *pwrb_context; | 763 | struct hwi_wrb_context *pwrb_context; |
488 | struct hwi_controller *phwi_ctrlr; | 764 | struct hwi_controller *phwi_ctrlr; |
489 | struct wrb_handle *pwrb_handle; | 765 | struct wrb_handle *pwrb_handle, *pwrb_handle_tmp; |
490 | 766 | ||
491 | phwi_ctrlr = phba->phwi_ctrlr; | 767 | phwi_ctrlr = phba->phwi_ctrlr; |
492 | pwrb_context = &phwi_ctrlr->wrb_context[cid]; | 768 | pwrb_context = &phwi_ctrlr->wrb_context[cid]; |
493 | pwrb_handle = pwrb_context->pwrb_handle_base[index]; | 769 | if (pwrb_context->wrb_handles_available >= 2) { |
494 | pwrb_handle->wrb_index = index; | 770 | pwrb_handle = pwrb_context->pwrb_handle_base[ |
495 | pwrb_handle->nxt_wrb_index = index; | 771 | pwrb_context->alloc_index]; |
772 | pwrb_context->wrb_handles_available--; | ||
773 | if (pwrb_context->alloc_index == | ||
774 | (phba->params.wrbs_per_cxn - 1)) | ||
775 | pwrb_context->alloc_index = 0; | ||
776 | else | ||
777 | pwrb_context->alloc_index++; | ||
778 | pwrb_handle_tmp = pwrb_context->pwrb_handle_base[ | ||
779 | pwrb_context->alloc_index]; | ||
780 | pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index; | ||
781 | } else | ||
782 | pwrb_handle = NULL; | ||
496 | return pwrb_handle; | 783 | return pwrb_handle; |
497 | } | 784 | } |
498 | 785 | ||
@@ -508,11 +795,18 @@ static void | |||
508 | free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, | 795 | free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, |
509 | struct wrb_handle *pwrb_handle) | 796 | struct wrb_handle *pwrb_handle) |
510 | { | 797 | { |
798 | pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; | ||
799 | pwrb_context->wrb_handles_available++; | ||
800 | if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) | ||
801 | pwrb_context->free_index = 0; | ||
802 | else | ||
803 | pwrb_context->free_index++; | ||
804 | |||
511 | SE_DEBUG(DBG_LVL_8, | 805 | SE_DEBUG(DBG_LVL_8, |
512 | "FREE WRB: pwrb_handle=%p free_index=%d=0x%x" | 806 | "FREE WRB: pwrb_handle=%p free_index=0x%x" |
513 | "wrb_handles_available=%d \n", | 807 | "wrb_handles_available=%d \n", |
514 | pwrb_handle, pwrb_context->free_index, | 808 | pwrb_handle, pwrb_context->free_index, |
515 | pwrb_context->free_index, pwrb_context->wrb_handles_available); | 809 | pwrb_context->wrb_handles_available); |
516 | } | 810 | } |
517 | 811 | ||
518 | static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) | 812 | static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) |
@@ -540,6 +834,8 @@ void | |||
540 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) | 834 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) |
541 | { | 835 | { |
542 | 836 | ||
837 | SE_DEBUG(DBG_LVL_8, "In free_mgmt_sgl_handle,eh_sgl_free_index=%d \n", | ||
838 | phba->eh_sgl_free_index); | ||
543 | if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) { | 839 | if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) { |
544 | /* | 840 | /* |
545 | * this can happen if clean_task is called on a task that | 841 | * this can happen if clean_task is called on a task that |
@@ -572,10 +868,10 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, | |||
572 | u32 resid = 0, exp_cmdsn, max_cmdsn; | 868 | u32 resid = 0, exp_cmdsn, max_cmdsn; |
573 | u8 rsp, status, flags; | 869 | u8 rsp, status, flags; |
574 | 870 | ||
575 | exp_cmdsn = be32_to_cpu(psol-> | 871 | exp_cmdsn = (psol-> |
576 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | 872 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] |
577 | & SOL_EXP_CMD_SN_MASK); | 873 | & SOL_EXP_CMD_SN_MASK); |
578 | max_cmdsn = be32_to_cpu((psol-> | 874 | max_cmdsn = ((psol-> |
579 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | 875 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] |
580 | & SOL_EXP_CMD_SN_MASK) + | 876 | & SOL_EXP_CMD_SN_MASK) + |
581 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | 877 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) |
@@ -610,18 +906,19 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, | |||
610 | } | 906 | } |
611 | 907 | ||
612 | if (status == SAM_STAT_CHECK_CONDITION) { | 908 | if (status == SAM_STAT_CHECK_CONDITION) { |
909 | unsigned short *slen = (unsigned short *)sts_bhs->sense_info; | ||
613 | sense = sts_bhs->sense_info + sizeof(unsigned short); | 910 | sense = sts_bhs->sense_info + sizeof(unsigned short); |
614 | sense_len = | 911 | sense_len = cpu_to_be16(*slen); |
615 | cpu_to_be16((unsigned short)(sts_bhs->sense_info[0])); | ||
616 | memcpy(task->sc->sense_buffer, sense, | 912 | memcpy(task->sc->sense_buffer, sense, |
617 | min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); | 913 | min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); |
618 | } | 914 | } |
915 | |||
619 | if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { | 916 | 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] | 917 | if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] |
621 | & SOL_RES_CNT_MASK) | 918 | & SOL_RES_CNT_MASK) |
622 | conn->rxdata_octets += (psol-> | 919 | conn->rxdata_octets += (psol-> |
623 | dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] | 920 | dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] |
624 | & SOL_RES_CNT_MASK); | 921 | & SOL_RES_CNT_MASK); |
625 | } | 922 | } |
626 | unmap: | 923 | unmap: |
627 | scsi_dma_unmap(io_task->scsi_cmnd); | 924 | scsi_dma_unmap(io_task->scsi_cmnd); |
@@ -633,9 +930,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn, | |||
633 | struct iscsi_task *task, struct sol_cqe *psol) | 930 | struct iscsi_task *task, struct sol_cqe *psol) |
634 | { | 931 | { |
635 | struct iscsi_logout_rsp *hdr; | 932 | struct iscsi_logout_rsp *hdr; |
933 | struct beiscsi_io_task *io_task = task->dd_data; | ||
636 | struct iscsi_conn *conn = beiscsi_conn->conn; | 934 | struct iscsi_conn *conn = beiscsi_conn->conn; |
637 | 935 | ||
638 | hdr = (struct iscsi_logout_rsp *)task->hdr; | 936 | hdr = (struct iscsi_logout_rsp *)task->hdr; |
937 | hdr->opcode = ISCSI_OP_LOGOUT_RSP; | ||
639 | hdr->t2wait = 5; | 938 | hdr->t2wait = 5; |
640 | hdr->t2retain = 0; | 939 | hdr->t2retain = 0; |
641 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | 940 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] |
@@ -650,8 +949,11 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn, | |||
650 | & SOL_EXP_CMD_SN_MASK) + | 949 | & SOL_EXP_CMD_SN_MASK) + |
651 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | 950 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) |
652 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | 951 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); |
952 | hdr->dlength[0] = 0; | ||
953 | hdr->dlength[1] = 0; | ||
954 | hdr->dlength[2] = 0; | ||
653 | hdr->hlength = 0; | 955 | hdr->hlength = 0; |
654 | 956 | hdr->itt = io_task->libiscsi_itt; | |
655 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | 957 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); |
656 | } | 958 | } |
657 | 959 | ||
@@ -661,18 +963,21 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn, | |||
661 | { | 963 | { |
662 | struct iscsi_tm_rsp *hdr; | 964 | struct iscsi_tm_rsp *hdr; |
663 | struct iscsi_conn *conn = beiscsi_conn->conn; | 965 | struct iscsi_conn *conn = beiscsi_conn->conn; |
966 | struct beiscsi_io_task *io_task = task->dd_data; | ||
664 | 967 | ||
665 | hdr = (struct iscsi_tm_rsp *)task->hdr; | 968 | hdr = (struct iscsi_tm_rsp *)task->hdr; |
969 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; | ||
666 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | 970 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] |
667 | & SOL_FLAGS_MASK) >> 24) | 0x80; | 971 | & SOL_FLAGS_MASK) >> 24) | 0x80; |
668 | hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / | 972 | hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / |
669 | 32] & SOL_RESP_MASK); | 973 | 32] & SOL_RESP_MASK); |
670 | hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, | 974 | hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, |
671 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); | 975 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); |
672 | hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, | 976 | hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, |
673 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + | 977 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + |
674 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | 978 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) |
675 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | 979 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); |
980 | hdr->itt = io_task->libiscsi_itt; | ||
676 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | 981 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); |
677 | } | 982 | } |
678 | 983 | ||
@@ -681,18 +986,27 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | |||
681 | struct beiscsi_hba *phba, struct sol_cqe *psol) | 986 | struct beiscsi_hba *phba, struct sol_cqe *psol) |
682 | { | 987 | { |
683 | struct hwi_wrb_context *pwrb_context; | 988 | struct hwi_wrb_context *pwrb_context; |
684 | struct wrb_handle *pwrb_handle; | 989 | struct wrb_handle *pwrb_handle = NULL; |
685 | struct hwi_controller *phwi_ctrlr; | 990 | struct hwi_controller *phwi_ctrlr; |
991 | struct iscsi_task *task; | ||
992 | struct beiscsi_io_task *io_task; | ||
686 | struct iscsi_conn *conn = beiscsi_conn->conn; | 993 | struct iscsi_conn *conn = beiscsi_conn->conn; |
687 | struct iscsi_session *session = conn->session; | 994 | struct iscsi_session *session = conn->session; |
688 | 995 | ||
689 | phwi_ctrlr = phba->phwi_ctrlr; | 996 | phwi_ctrlr = phba->phwi_ctrlr; |
690 | pwrb_context = &phwi_ctrlr->wrb_context[((psol-> | 997 | pwrb_context = &phwi_ctrlr->wrb_context[((psol-> |
691 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & | 998 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & |
692 | SOL_CID_MASK) >> 6)]; | 999 | SOL_CID_MASK) >> 6) - |
1000 | phba->fw_config.iscsi_cid_start]; | ||
693 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> | 1001 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> |
694 | dw[offsetof(struct amap_sol_cqe, wrb_index) / | 1002 | dw[offsetof(struct amap_sol_cqe, wrb_index) / |
695 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; | 1003 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; |
1004 | task = pwrb_handle->pio_handle; | ||
1005 | |||
1006 | io_task = task->dd_data; | ||
1007 | spin_lock(&phba->mgmt_sgl_lock); | ||
1008 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); | ||
1009 | spin_unlock(&phba->mgmt_sgl_lock); | ||
696 | spin_lock_bh(&session->lock); | 1010 | spin_lock_bh(&session->lock); |
697 | free_wrb_handle(phba, pwrb_context, pwrb_handle); | 1011 | free_wrb_handle(phba, pwrb_context, pwrb_handle); |
698 | spin_unlock_bh(&session->lock); | 1012 | spin_unlock_bh(&session->lock); |
@@ -704,6 +1018,7 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, | |||
704 | { | 1018 | { |
705 | struct iscsi_nopin *hdr; | 1019 | struct iscsi_nopin *hdr; |
706 | struct iscsi_conn *conn = beiscsi_conn->conn; | 1020 | struct iscsi_conn *conn = beiscsi_conn->conn; |
1021 | struct beiscsi_io_task *io_task = task->dd_data; | ||
707 | 1022 | ||
708 | hdr = (struct iscsi_nopin *)task->hdr; | 1023 | hdr = (struct iscsi_nopin *)task->hdr; |
709 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | 1024 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] |
@@ -715,6 +1030,7 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, | |||
715 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | 1030 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) |
716 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | 1031 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); |
717 | hdr->opcode = ISCSI_OP_NOOP_IN; | 1032 | hdr->opcode = ISCSI_OP_NOOP_IN; |
1033 | hdr->itt = io_task->libiscsi_itt; | ||
718 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | 1034 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); |
719 | } | 1035 | } |
720 | 1036 | ||
@@ -726,36 +1042,40 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | |||
726 | struct iscsi_wrb *pwrb = NULL; | 1042 | struct iscsi_wrb *pwrb = NULL; |
727 | struct hwi_controller *phwi_ctrlr; | 1043 | struct hwi_controller *phwi_ctrlr; |
728 | struct iscsi_task *task; | 1044 | struct iscsi_task *task; |
729 | struct beiscsi_io_task *io_task; | 1045 | unsigned int type; |
730 | struct iscsi_conn *conn = beiscsi_conn->conn; | 1046 | struct iscsi_conn *conn = beiscsi_conn->conn; |
731 | struct iscsi_session *session = conn->session; | 1047 | struct iscsi_session *session = conn->session; |
732 | 1048 | ||
733 | phwi_ctrlr = phba->phwi_ctrlr; | 1049 | phwi_ctrlr = phba->phwi_ctrlr; |
734 | 1050 | pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof | |
735 | pwrb_context = &phwi_ctrlr-> | 1051 | (struct amap_sol_cqe, cid) / 32] |
736 | wrb_context[((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32] | 1052 | & SOL_CID_MASK) >> 6) - |
737 | & SOL_CID_MASK) >> 6)]; | 1053 | phba->fw_config.iscsi_cid_start]; |
738 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> | 1054 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> |
739 | dw[offsetof(struct amap_sol_cqe, wrb_index) / | 1055 | dw[offsetof(struct amap_sol_cqe, wrb_index) / |
740 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; | 1056 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; |
741 | |||
742 | task = pwrb_handle->pio_handle; | 1057 | task = pwrb_handle->pio_handle; |
743 | io_task = task->dd_data; | ||
744 | spin_lock_bh(&session->lock); | ||
745 | pwrb = pwrb_handle->pwrb; | 1058 | pwrb = pwrb_handle->pwrb; |
746 | switch ((pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] & | 1059 | type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] & |
747 | WRB_TYPE_MASK) >> 28) { | 1060 | WRB_TYPE_MASK) >> 28; |
1061 | |||
1062 | spin_lock_bh(&session->lock); | ||
1063 | switch (type) { | ||
748 | case HWH_TYPE_IO: | 1064 | case HWH_TYPE_IO: |
749 | case HWH_TYPE_IO_RD: | 1065 | case HWH_TYPE_IO_RD: |
750 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == | 1066 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == |
751 | ISCSI_OP_NOOP_OUT) { | 1067 | ISCSI_OP_NOOP_OUT) |
752 | be_complete_nopin_resp(beiscsi_conn, task, psol); | 1068 | be_complete_nopin_resp(beiscsi_conn, task, psol); |
753 | } else | 1069 | else |
754 | be_complete_io(beiscsi_conn, task, psol); | 1070 | be_complete_io(beiscsi_conn, task, psol); |
755 | break; | 1071 | break; |
756 | 1072 | ||
757 | case HWH_TYPE_LOGOUT: | 1073 | case HWH_TYPE_LOGOUT: |
758 | be_complete_logout(beiscsi_conn, task, psol); | 1074 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) |
1075 | be_complete_logout(beiscsi_conn, task, psol); | ||
1076 | else | ||
1077 | be_complete_tmf(beiscsi_conn, task, psol); | ||
1078 | |||
759 | break; | 1079 | break; |
760 | 1080 | ||
761 | case HWH_TYPE_LOGIN: | 1081 | case HWH_TYPE_LOGIN: |
@@ -764,21 +1084,18 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | |||
764 | "- Solicited path \n"); | 1084 | "- Solicited path \n"); |
765 | break; | 1085 | break; |
766 | 1086 | ||
767 | case HWH_TYPE_TMF: | ||
768 | be_complete_tmf(beiscsi_conn, task, psol); | ||
769 | break; | ||
770 | |||
771 | case HWH_TYPE_NOP: | 1087 | case HWH_TYPE_NOP: |
772 | be_complete_nopin_resp(beiscsi_conn, task, psol); | 1088 | be_complete_nopin_resp(beiscsi_conn, task, psol); |
773 | break; | 1089 | break; |
774 | 1090 | ||
775 | default: | 1091 | default: |
776 | shost_printk(KERN_WARNING, phba->shost, | 1092 | shost_printk(KERN_WARNING, phba->shost, |
777 | "wrb_index 0x%x CID 0x%x\n", | 1093 | "In hwi_complete_cmd, unknown type = %d" |
778 | ((psol->dw[offsetof(struct amap_iscsi_wrb, type) / | 1094 | "wrb_index 0x%x CID 0x%x\n", type, |
779 | 32] & SOL_WRB_INDEX_MASK) >> 16), | 1095 | ((psol->dw[offsetof(struct amap_iscsi_wrb, |
780 | ((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32] | 1096 | type) / 32] & SOL_WRB_INDEX_MASK) >> 16), |
781 | & SOL_CID_MASK) >> 6)); | 1097 | ((psol->dw[offsetof(struct amap_sol_cqe, |
1098 | cid) / 32] & SOL_CID_MASK) >> 6)); | ||
782 | break; | 1099 | break; |
783 | } | 1100 | } |
784 | 1101 | ||
@@ -863,7 +1180,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba, | |||
863 | 1180 | ||
864 | WARN_ON(!pasync_handle); | 1181 | WARN_ON(!pasync_handle); |
865 | 1182 | ||
866 | pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid; | 1183 | pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid - |
1184 | phba->fw_config.iscsi_cid_start; | ||
867 | pasync_handle->is_header = is_header; | 1185 | pasync_handle->is_header = is_header; |
868 | pasync_handle->buffer_len = ((pdpdu_cqe-> | 1186 | pasync_handle->buffer_len = ((pdpdu_cqe-> |
869 | dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] | 1187 | dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] |
@@ -1113,9 +1431,10 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, | |||
1113 | } | 1431 | } |
1114 | 1432 | ||
1115 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, | 1433 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, |
1116 | beiscsi_conn->beiscsi_conn_cid, | 1434 | (beiscsi_conn->beiscsi_conn_cid - |
1117 | phdr, hdr_len, pfirst_buffer, | 1435 | phba->fw_config.iscsi_cid_start), |
1118 | buf_len); | 1436 | phdr, hdr_len, pfirst_buffer, |
1437 | buf_len); | ||
1119 | 1438 | ||
1120 | if (status == 0) | 1439 | if (status == 0) |
1121 | hwi_free_async_msg(phba, cri); | 1440 | hwi_free_async_msg(phba, cri); |
@@ -1208,40 +1527,79 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | |||
1208 | hwi_post_async_buffers(phba, pasync_handle->is_header); | 1527 | hwi_post_async_buffers(phba, pasync_handle->is_header); |
1209 | } | 1528 | } |
1210 | 1529 | ||
1211 | static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | 1530 | static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) |
1531 | { | ||
1532 | struct be_queue_info *mcc_cq; | ||
1533 | struct be_mcc_compl *mcc_compl; | ||
1534 | unsigned int num_processed = 0; | ||
1535 | |||
1536 | mcc_cq = &phba->ctrl.mcc_obj.cq; | ||
1537 | mcc_compl = queue_tail_node(mcc_cq); | ||
1538 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); | ||
1539 | while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { | ||
1540 | |||
1541 | if (num_processed >= 32) { | ||
1542 | hwi_ring_cq_db(phba, mcc_cq->id, | ||
1543 | num_processed, 0, 0); | ||
1544 | num_processed = 0; | ||
1545 | } | ||
1546 | if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { | ||
1547 | /* Interpret flags as an async trailer */ | ||
1548 | if (is_link_state_evt(mcc_compl->flags)) | ||
1549 | /* Interpret compl as a async link evt */ | ||
1550 | beiscsi_async_link_state_process(phba, | ||
1551 | (struct be_async_event_link_state *) mcc_compl); | ||
1552 | else | ||
1553 | SE_DEBUG(DBG_LVL_1, | ||
1554 | " Unsupported Async Event, flags" | ||
1555 | " = 0x%08x \n", mcc_compl->flags); | ||
1556 | } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) { | ||
1557 | be_mcc_compl_process_isr(&phba->ctrl, mcc_compl); | ||
1558 | atomic_dec(&phba->ctrl.mcc_obj.q.used); | ||
1559 | } | ||
1560 | |||
1561 | mcc_compl->flags = 0; | ||
1562 | queue_tail_inc(mcc_cq); | ||
1563 | mcc_compl = queue_tail_node(mcc_cq); | ||
1564 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); | ||
1565 | num_processed++; | ||
1566 | } | ||
1567 | |||
1568 | if (num_processed > 0) | ||
1569 | hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); | ||
1570 | |||
1571 | } | ||
1572 | |||
1573 | static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | ||
1212 | { | 1574 | { |
1213 | struct hwi_controller *phwi_ctrlr; | ||
1214 | struct hwi_context_memory *phwi_context; | ||
1215 | struct be_queue_info *cq; | 1575 | struct be_queue_info *cq; |
1216 | struct sol_cqe *sol; | 1576 | struct sol_cqe *sol; |
1217 | struct dmsg_cqe *dmsg; | 1577 | struct dmsg_cqe *dmsg; |
1218 | unsigned int num_processed = 0; | 1578 | unsigned int num_processed = 0; |
1219 | unsigned int tot_nump = 0; | 1579 | unsigned int tot_nump = 0; |
1220 | struct beiscsi_conn *beiscsi_conn; | 1580 | struct beiscsi_conn *beiscsi_conn; |
1581 | struct beiscsi_endpoint *beiscsi_ep; | ||
1582 | struct iscsi_endpoint *ep; | ||
1583 | struct beiscsi_hba *phba; | ||
1221 | 1584 | ||
1222 | phwi_ctrlr = phba->phwi_ctrlr; | 1585 | cq = pbe_eq->cq; |
1223 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
1224 | cq = &phwi_context->be_cq; | ||
1225 | sol = queue_tail_node(cq); | 1586 | sol = queue_tail_node(cq); |
1587 | phba = pbe_eq->phba; | ||
1226 | 1588 | ||
1227 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & | 1589 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & |
1228 | CQE_VALID_MASK) { | 1590 | CQE_VALID_MASK) { |
1229 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); | 1591 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); |
1230 | 1592 | ||
1231 | beiscsi_conn = phba->conn_table[(u32) (sol-> | 1593 | ep = phba->ep_array[(u32) ((sol-> |
1232 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & | 1594 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & |
1233 | SOL_CID_MASK) >> 6]; | 1595 | SOL_CID_MASK) >> 6) - |
1596 | phba->fw_config.iscsi_cid_start]; | ||
1234 | 1597 | ||
1235 | if (!beiscsi_conn || !beiscsi_conn->ep) { | 1598 | beiscsi_ep = ep->dd_data; |
1236 | shost_printk(KERN_WARNING, phba->shost, | 1599 | beiscsi_conn = beiscsi_ep->conn; |
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 | 1600 | ||
1243 | if (num_processed >= 32) { | 1601 | if (num_processed >= 32) { |
1244 | hwi_ring_cq_db(phba, phwi_context->be_cq.id, | 1602 | hwi_ring_cq_db(phba, cq->id, |
1245 | num_processed, 0, 0); | 1603 | num_processed, 0, 0); |
1246 | tot_nump += num_processed; | 1604 | tot_nump += num_processed; |
1247 | num_processed = 0; | 1605 | num_processed = 0; |
@@ -1258,8 +1616,12 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | |||
1258 | hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); | 1616 | hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); |
1259 | break; | 1617 | break; |
1260 | case UNSOL_HDR_NOTIFY: | 1618 | case UNSOL_HDR_NOTIFY: |
1619 | SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR_ NOTIFY\n"); | ||
1620 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | ||
1621 | (struct i_t_dpdu_cqe *)sol); | ||
1622 | break; | ||
1261 | case UNSOL_DATA_NOTIFY: | 1623 | case UNSOL_DATA_NOTIFY: |
1262 | SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR/DATA_NOTIFY\n"); | 1624 | SE_DEBUG(DBG_LVL_8, "Received UNSOL_DATA_NOTIFY\n"); |
1263 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | 1625 | hwi_process_default_pdu_ring(beiscsi_conn, phba, |
1264 | (struct i_t_dpdu_cqe *)sol); | 1626 | (struct i_t_dpdu_cqe *)sol); |
1265 | break; | 1627 | break; |
@@ -1306,23 +1668,23 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | |||
1306 | case CXN_KILLED_OVER_RUN_RESIDUAL: | 1668 | case CXN_KILLED_OVER_RUN_RESIDUAL: |
1307 | case CXN_KILLED_UNDER_RUN_RESIDUAL: | 1669 | case CXN_KILLED_UNDER_RUN_RESIDUAL: |
1308 | case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: | 1670 | case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: |
1309 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, resetting CID " | 1671 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset CID " |
1310 | "0x%x...\n", | 1672 | "0x%x...\n", |
1311 | sol->dw[offsetof(struct amap_sol_cqe, code) / | 1673 | sol->dw[offsetof(struct amap_sol_cqe, code) / |
1312 | 32] & CQE_CODE_MASK, | 1674 | 32] & CQE_CODE_MASK, |
1313 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | 1675 | (sol->dw[offsetof(struct amap_sol_cqe, cid) / |
1314 | 32] & CQE_CID_MASK); | 1676 | 32] & CQE_CID_MASK)); |
1315 | iscsi_conn_failure(beiscsi_conn->conn, | 1677 | iscsi_conn_failure(beiscsi_conn->conn, |
1316 | ISCSI_ERR_CONN_FAILED); | 1678 | ISCSI_ERR_CONN_FAILED); |
1317 | break; | 1679 | break; |
1318 | case CXN_KILLED_RST_SENT: | 1680 | case CXN_KILLED_RST_SENT: |
1319 | case CXN_KILLED_RST_RCVD: | 1681 | case CXN_KILLED_RST_RCVD: |
1320 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset received/sent " | 1682 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset" |
1321 | "on CID 0x%x...\n", | 1683 | "received/sent on CID 0x%x...\n", |
1322 | sol->dw[offsetof(struct amap_sol_cqe, code) / | 1684 | sol->dw[offsetof(struct amap_sol_cqe, code) / |
1323 | 32] & CQE_CODE_MASK, | 1685 | 32] & CQE_CODE_MASK, |
1324 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | 1686 | (sol->dw[offsetof(struct amap_sol_cqe, cid) / |
1325 | 32] & CQE_CID_MASK); | 1687 | 32] & CQE_CID_MASK)); |
1326 | iscsi_conn_failure(beiscsi_conn->conn, | 1688 | iscsi_conn_failure(beiscsi_conn->conn, |
1327 | ISCSI_ERR_CONN_FAILED); | 1689 | ISCSI_ERR_CONN_FAILED); |
1328 | break; | 1690 | break; |
@@ -1331,8 +1693,8 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | |||
1331 | "received on CID 0x%x...\n", | 1693 | "received on CID 0x%x...\n", |
1332 | sol->dw[offsetof(struct amap_sol_cqe, code) / | 1694 | sol->dw[offsetof(struct amap_sol_cqe, code) / |
1333 | 32] & CQE_CODE_MASK, | 1695 | 32] & CQE_CODE_MASK, |
1334 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | 1696 | (sol->dw[offsetof(struct amap_sol_cqe, cid) / |
1335 | 32] & CQE_CID_MASK); | 1697 | 32] & CQE_CID_MASK)); |
1336 | break; | 1698 | break; |
1337 | } | 1699 | } |
1338 | 1700 | ||
@@ -1344,30 +1706,39 @@ static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | |||
1344 | 1706 | ||
1345 | if (num_processed > 0) { | 1707 | if (num_processed > 0) { |
1346 | tot_nump += num_processed; | 1708 | tot_nump += num_processed; |
1347 | hwi_ring_cq_db(phba, phwi_context->be_cq.id, num_processed, | 1709 | hwi_ring_cq_db(phba, cq->id, num_processed, 1, 0); |
1348 | 1, 0); | ||
1349 | } | 1710 | } |
1350 | return tot_nump; | 1711 | return tot_nump; |
1351 | } | 1712 | } |
1352 | 1713 | ||
1353 | static void beiscsi_process_all_cqs(struct work_struct *work) | 1714 | void beiscsi_process_all_cqs(struct work_struct *work) |
1354 | { | 1715 | { |
1355 | unsigned long flags; | 1716 | unsigned long flags; |
1717 | struct hwi_controller *phwi_ctrlr; | ||
1718 | struct hwi_context_memory *phwi_context; | ||
1719 | struct be_eq_obj *pbe_eq; | ||
1356 | struct beiscsi_hba *phba = | 1720 | struct beiscsi_hba *phba = |
1357 | container_of(work, struct beiscsi_hba, work_cqs); | 1721 | container_of(work, struct beiscsi_hba, work_cqs); |
1358 | 1722 | ||
1723 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1724 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
1725 | if (phba->msix_enabled) | ||
1726 | pbe_eq = &phwi_context->be_eq[phba->num_cpus]; | ||
1727 | else | ||
1728 | pbe_eq = &phwi_context->be_eq[0]; | ||
1729 | |||
1359 | if (phba->todo_mcc_cq) { | 1730 | if (phba->todo_mcc_cq) { |
1360 | spin_lock_irqsave(&phba->isr_lock, flags); | 1731 | spin_lock_irqsave(&phba->isr_lock, flags); |
1361 | phba->todo_mcc_cq = 0; | 1732 | phba->todo_mcc_cq = 0; |
1362 | spin_unlock_irqrestore(&phba->isr_lock, flags); | 1733 | spin_unlock_irqrestore(&phba->isr_lock, flags); |
1363 | SE_DEBUG(DBG_LVL_1, "MCC Interrupt Not expected \n"); | 1734 | beiscsi_process_mcc_isr(phba); |
1364 | } | 1735 | } |
1365 | 1736 | ||
1366 | if (phba->todo_cq) { | 1737 | if (phba->todo_cq) { |
1367 | spin_lock_irqsave(&phba->isr_lock, flags); | 1738 | spin_lock_irqsave(&phba->isr_lock, flags); |
1368 | phba->todo_cq = 0; | 1739 | phba->todo_cq = 0; |
1369 | spin_unlock_irqrestore(&phba->isr_lock, flags); | 1740 | spin_unlock_irqrestore(&phba->isr_lock, flags); |
1370 | beiscsi_process_cq(phba); | 1741 | beiscsi_process_cq(pbe_eq); |
1371 | } | 1742 | } |
1372 | } | 1743 | } |
1373 | 1744 | ||
@@ -1375,19 +1746,15 @@ static int be_iopoll(struct blk_iopoll *iop, int budget) | |||
1375 | { | 1746 | { |
1376 | static unsigned int ret; | 1747 | static unsigned int ret; |
1377 | struct beiscsi_hba *phba; | 1748 | struct beiscsi_hba *phba; |
1749 | struct be_eq_obj *pbe_eq; | ||
1378 | 1750 | ||
1379 | phba = container_of(iop, struct beiscsi_hba, iopoll); | 1751 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); |
1380 | 1752 | ret = beiscsi_process_cq(pbe_eq); | |
1381 | ret = beiscsi_process_cq(phba); | ||
1382 | if (ret < budget) { | 1753 | if (ret < budget) { |
1383 | struct hwi_controller *phwi_ctrlr; | 1754 | phba = pbe_eq->phba; |
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); | 1755 | blk_iopoll_complete(iop); |
1389 | hwi_ring_eq_db(phba, phwi_context->be_eq.q.id, 0, | 1756 | SE_DEBUG(DBG_LVL_8, "rearm pbe_eq->q.id =%d\n", pbe_eq->q.id); |
1390 | 0, 1, 1); | 1757 | hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); |
1391 | } | 1758 | } |
1392 | return ret; | 1759 | return ret; |
1393 | } | 1760 | } |
@@ -1409,7 +1776,8 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, | |||
1409 | io_task->bhs_pa.u.a32.address_hi); | 1776 | io_task->bhs_pa.u.a32.address_hi); |
1410 | 1777 | ||
1411 | l_sg = sg; | 1778 | l_sg = sg; |
1412 | for (index = 0; (index < num_sg) && (index < 2); index++, sg_next(sg)) { | 1779 | for (index = 0; (index < num_sg) && (index < 2); index++, |
1780 | sg = sg_next(sg)) { | ||
1413 | if (index == 0) { | 1781 | if (index == 0) { |
1414 | sg_len = sg_dma_len(sg); | 1782 | sg_len = sg_dma_len(sg); |
1415 | addr = (u64) sg_dma_address(sg); | 1783 | addr = (u64) sg_dma_address(sg); |
@@ -1420,11 +1788,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, | |||
1420 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, | 1788 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, |
1421 | sg_len); | 1789 | sg_len); |
1422 | sge_len = sg_len; | 1790 | sge_len = sg_len; |
1423 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, | ||
1424 | 1); | ||
1425 | } else { | 1791 | } 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, | 1792 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset, |
1429 | pwrb, sge_len); | 1793 | pwrb, sge_len); |
1430 | sg_len = sg_dma_len(sg); | 1794 | sg_len = sg_dma_len(sg); |
@@ -1447,13 +1811,27 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, | |||
1447 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | 1811 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, |
1448 | io_task->bhs_pa.u.a32.address_lo); | 1812 | io_task->bhs_pa.u.a32.address_lo); |
1449 | 1813 | ||
1450 | if (num_sg == 2) | 1814 | if (num_sg == 1) { |
1451 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 1); | 1815 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, |
1816 | 1); | ||
1817 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, | ||
1818 | 0); | ||
1819 | } else if (num_sg == 2) { | ||
1820 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, | ||
1821 | 0); | ||
1822 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, | ||
1823 | 1); | ||
1824 | } else { | ||
1825 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, | ||
1826 | 0); | ||
1827 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, | ||
1828 | 0); | ||
1829 | } | ||
1452 | sg = l_sg; | 1830 | sg = l_sg; |
1453 | psgl++; | 1831 | psgl++; |
1454 | psgl++; | 1832 | psgl++; |
1455 | offset = 0; | 1833 | offset = 0; |
1456 | for (index = 0; index < num_sg; index++, sg_next(sg), psgl++) { | 1834 | for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) { |
1457 | sg_len = sg_dma_len(sg); | 1835 | sg_len = sg_dma_len(sg); |
1458 | addr = (u64) sg_dma_address(sg); | 1836 | addr = (u64) sg_dma_address(sg); |
1459 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | 1837 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, |
@@ -1537,14 +1915,12 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) | |||
1537 | 1915 | ||
1538 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | 1916 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) |
1539 | { | 1917 | { |
1540 | unsigned int num_cq_pages, num_eq_pages, num_async_pdu_buf_pages; | 1918 | unsigned int num_cq_pages, num_async_pdu_buf_pages; |
1541 | unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; | 1919 | 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; | 1920 | unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; |
1543 | 1921 | ||
1544 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ | 1922 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ |
1545 | sizeof(struct sol_cqe)); | 1923 | 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 = | 1924 | num_async_pdu_buf_pages = |
1549 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | 1925 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ |
1550 | phba->params.defpdu_hdr_sz); | 1926 | phba->params.defpdu_hdr_sz); |
@@ -1565,8 +1941,6 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | |||
1565 | phba->mem_req[HWI_MEM_ADDN_CONTEXT] = | 1941 | phba->mem_req[HWI_MEM_ADDN_CONTEXT] = |
1566 | sizeof(struct hwi_context_memory); | 1942 | sizeof(struct hwi_context_memory); |
1567 | 1943 | ||
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 | 1944 | ||
1571 | phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb) | 1945 | phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb) |
1572 | * (phba->params.wrbs_per_cxn) | 1946 | * (phba->params.wrbs_per_cxn) |
@@ -1751,8 +2125,6 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
1751 | 2125 | ||
1752 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | 2126 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { |
1753 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 2127 | 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 = | 2128 | pwrb_context->pwrb_handle_base = |
1757 | kzalloc(sizeof(struct wrb_handle *) * | 2129 | kzalloc(sizeof(struct wrb_handle *) * |
1758 | phba->params.wrbs_per_cxn, GFP_KERNEL); | 2130 | phba->params.wrbs_per_cxn, GFP_KERNEL); |
@@ -1767,6 +2139,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
1767 | pwrb_context->pwrb_handle_basestd[j] = | 2139 | pwrb_context->pwrb_handle_basestd[j] = |
1768 | pwrb_handle; | 2140 | pwrb_handle; |
1769 | pwrb_context->wrb_handles_available++; | 2141 | pwrb_context->wrb_handles_available++; |
2142 | pwrb_handle->wrb_index = j; | ||
1770 | pwrb_handle++; | 2143 | pwrb_handle++; |
1771 | } | 2144 | } |
1772 | pwrb_context->free_index = 0; | 2145 | pwrb_context->free_index = 0; |
@@ -1785,6 +2158,7 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
1785 | pwrb_context->pwrb_handle_basestd[j] = | 2158 | pwrb_context->pwrb_handle_basestd[j] = |
1786 | pwrb_handle; | 2159 | pwrb_handle; |
1787 | pwrb_context->wrb_handles_available++; | 2160 | pwrb_context->wrb_handles_available++; |
2161 | pwrb_handle->wrb_index = j; | ||
1788 | pwrb_handle++; | 2162 | pwrb_handle++; |
1789 | } | 2163 | } |
1790 | pwrb_context->free_index = 0; | 2164 | pwrb_context->free_index = 0; |
@@ -1793,11 +2167,10 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
1793 | } | 2167 | } |
1794 | idx = 0; | 2168 | idx = 0; |
1795 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; | 2169 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; |
1796 | num_cxn_wrb = | 2170 | num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / |
1797 | ((mem_descr_wrb->mem_array[idx].size) / (sizeof(struct iscsi_wrb)) * | 2171 | ((sizeof(struct iscsi_wrb) * |
1798 | phba->params.wrbs_per_cxn); | 2172 | phba->params.wrbs_per_cxn)); |
1799 | 2173 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | |
1800 | for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) { | ||
1801 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 2174 | pwrb_context = &phwi_ctrlr->wrb_context[index]; |
1802 | if (num_cxn_wrb) { | 2175 | if (num_cxn_wrb) { |
1803 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | 2176 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { |
@@ -1809,9 +2182,9 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
1809 | } else { | 2182 | } else { |
1810 | idx++; | 2183 | idx++; |
1811 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; | 2184 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; |
1812 | num_cxn_wrb = ((mem_descr_wrb->mem_array[idx].size) / | 2185 | num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / |
1813 | (sizeof(struct iscsi_wrb)) * | 2186 | ((sizeof(struct iscsi_wrb) * |
1814 | phba->params.wrbs_per_cxn); | 2187 | phba->params.wrbs_per_cxn)); |
1815 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | 2188 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { |
1816 | pwrb_handle = pwrb_context->pwrb_handle_base[j]; | 2189 | pwrb_handle = pwrb_context->pwrb_handle_base[j]; |
1817 | pwrb_handle->pwrb = pwrb; | 2190 | pwrb_handle->pwrb = pwrb; |
@@ -2042,79 +2415,126 @@ static int be_fill_queue(struct be_queue_info *q, | |||
2042 | return 0; | 2415 | return 0; |
2043 | } | 2416 | } |
2044 | 2417 | ||
2045 | static int beiscsi_create_eq(struct beiscsi_hba *phba, | 2418 | static int beiscsi_create_eqs(struct beiscsi_hba *phba, |
2046 | struct hwi_context_memory *phwi_context) | 2419 | struct hwi_context_memory *phwi_context) |
2047 | { | 2420 | { |
2048 | unsigned int idx; | 2421 | unsigned int i, num_eq_pages; |
2049 | int ret; | 2422 | int ret, eq_for_mcc; |
2050 | struct be_queue_info *eq; | 2423 | struct be_queue_info *eq; |
2051 | struct be_dma_mem *mem; | 2424 | struct be_dma_mem *mem; |
2052 | struct be_mem_descriptor *mem_descr; | ||
2053 | void *eq_vaddress; | 2425 | void *eq_vaddress; |
2426 | dma_addr_t paddr; | ||
2054 | 2427 | ||
2055 | idx = 0; | 2428 | num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \ |
2056 | eq = &phwi_context->be_eq.q; | 2429 | sizeof(struct be_eq_entry)); |
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 | 2430 | ||
2070 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | 2431 | if (phba->msix_enabled) |
2432 | eq_for_mcc = 1; | ||
2433 | else | ||
2434 | eq_for_mcc = 0; | ||
2435 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { | ||
2436 | eq = &phwi_context->be_eq[i].q; | ||
2437 | mem = &eq->dma_mem; | ||
2438 | phwi_context->be_eq[i].phba = phba; | ||
2439 | eq_vaddress = pci_alloc_consistent(phba->pcidev, | ||
2440 | num_eq_pages * PAGE_SIZE, | ||
2441 | &paddr); | ||
2442 | if (!eq_vaddress) | ||
2443 | goto create_eq_error; | ||
2444 | |||
2445 | mem->va = eq_vaddress; | ||
2446 | ret = be_fill_queue(eq, phba->params.num_eq_entries, | ||
2447 | sizeof(struct be_eq_entry), eq_vaddress); | ||
2448 | if (ret) { | ||
2449 | shost_printk(KERN_ERR, phba->shost, | ||
2450 | "be_fill_queue Failed for EQ \n"); | ||
2451 | goto create_eq_error; | ||
2452 | } | ||
2071 | 2453 | ||
2072 | ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, | 2454 | mem->dma = paddr; |
2073 | phwi_context->be_eq.cur_eqd); | 2455 | ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, |
2074 | if (ret) { | 2456 | phwi_context->cur_eqd); |
2075 | shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create" | 2457 | if (ret) { |
2076 | "Failedfor EQ \n"); | 2458 | shost_printk(KERN_ERR, phba->shost, |
2077 | return ret; | 2459 | "beiscsi_cmd_eq_create" |
2460 | "Failedfor EQ \n"); | ||
2461 | goto create_eq_error; | ||
2462 | } | ||
2463 | SE_DEBUG(DBG_LVL_8, "eqid = %d\n", phwi_context->be_eq[i].q.id); | ||
2078 | } | 2464 | } |
2079 | SE_DEBUG(DBG_LVL_8, "eq id is %d\n", phwi_context->be_eq.q.id); | ||
2080 | return 0; | 2465 | return 0; |
2466 | create_eq_error: | ||
2467 | for (i = 0; i < (phba->num_cpus + 1); i++) { | ||
2468 | eq = &phwi_context->be_eq[i].q; | ||
2469 | mem = &eq->dma_mem; | ||
2470 | if (mem->va) | ||
2471 | pci_free_consistent(phba->pcidev, num_eq_pages | ||
2472 | * PAGE_SIZE, | ||
2473 | mem->va, mem->dma); | ||
2474 | } | ||
2475 | return ret; | ||
2081 | } | 2476 | } |
2082 | 2477 | ||
2083 | static int beiscsi_create_cq(struct beiscsi_hba *phba, | 2478 | static int beiscsi_create_cqs(struct beiscsi_hba *phba, |
2084 | struct hwi_context_memory *phwi_context) | 2479 | struct hwi_context_memory *phwi_context) |
2085 | { | 2480 | { |
2086 | unsigned int idx; | 2481 | unsigned int i, num_cq_pages; |
2087 | int ret; | 2482 | int ret; |
2088 | struct be_queue_info *cq, *eq; | 2483 | struct be_queue_info *cq, *eq; |
2089 | struct be_dma_mem *mem; | 2484 | struct be_dma_mem *mem; |
2090 | struct be_mem_descriptor *mem_descr; | 2485 | struct be_eq_obj *pbe_eq; |
2091 | void *cq_vaddress; | 2486 | void *cq_vaddress; |
2487 | dma_addr_t paddr; | ||
2092 | 2488 | ||
2093 | idx = 0; | 2489 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ |
2094 | cq = &phwi_context->be_cq; | 2490 | sizeof(struct sol_cqe)); |
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 | 2491 | ||
2108 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | 2492 | for (i = 0; i < phba->num_cpus; i++) { |
2109 | ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0); | 2493 | cq = &phwi_context->be_cq[i]; |
2110 | if (ret) { | 2494 | eq = &phwi_context->be_eq[i].q; |
2111 | shost_printk(KERN_ERR, phba->shost, | 2495 | pbe_eq = &phwi_context->be_eq[i]; |
2112 | "beiscsi_cmd_eq_create Failed for ISCSI CQ \n"); | 2496 | pbe_eq->cq = cq; |
2113 | return ret; | 2497 | pbe_eq->phba = phba; |
2498 | mem = &cq->dma_mem; | ||
2499 | cq_vaddress = pci_alloc_consistent(phba->pcidev, | ||
2500 | num_cq_pages * PAGE_SIZE, | ||
2501 | &paddr); | ||
2502 | if (!cq_vaddress) | ||
2503 | goto create_cq_error; | ||
2504 | ret = be_fill_queue(cq, phba->params.num_cq_entries, | ||
2505 | sizeof(struct sol_cqe), cq_vaddress); | ||
2506 | if (ret) { | ||
2507 | shost_printk(KERN_ERR, phba->shost, | ||
2508 | "be_fill_queue Failed for ISCSI CQ \n"); | ||
2509 | goto create_cq_error; | ||
2510 | } | ||
2511 | |||
2512 | mem->dma = paddr; | ||
2513 | ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, | ||
2514 | false, 0); | ||
2515 | if (ret) { | ||
2516 | shost_printk(KERN_ERR, phba->shost, | ||
2517 | "beiscsi_cmd_eq_create" | ||
2518 | "Failed for ISCSI CQ \n"); | ||
2519 | goto create_cq_error; | ||
2520 | } | ||
2521 | SE_DEBUG(DBG_LVL_8, "iscsi cq_id is %d for eq_id %d\n", | ||
2522 | cq->id, eq->id); | ||
2523 | SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n"); | ||
2114 | } | 2524 | } |
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; | 2525 | return 0; |
2526 | |||
2527 | create_cq_error: | ||
2528 | for (i = 0; i < phba->num_cpus; i++) { | ||
2529 | cq = &phwi_context->be_cq[i]; | ||
2530 | mem = &cq->dma_mem; | ||
2531 | if (mem->va) | ||
2532 | pci_free_consistent(phba->pcidev, num_cq_pages | ||
2533 | * PAGE_SIZE, | ||
2534 | mem->va, mem->dma); | ||
2535 | } | ||
2536 | return ret; | ||
2537 | |||
2118 | } | 2538 | } |
2119 | 2539 | ||
2120 | static int | 2540 | static int |
@@ -2132,7 +2552,7 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba, | |||
2132 | 2552 | ||
2133 | idx = 0; | 2553 | idx = 0; |
2134 | dq = &phwi_context->be_def_hdrq; | 2554 | dq = &phwi_context->be_def_hdrq; |
2135 | cq = &phwi_context->be_cq; | 2555 | cq = &phwi_context->be_cq[0]; |
2136 | mem = &dq->dma_mem; | 2556 | mem = &dq->dma_mem; |
2137 | mem_descr = phba->init_mem; | 2557 | mem_descr = phba->init_mem; |
2138 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; | 2558 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; |
@@ -2176,7 +2596,7 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, | |||
2176 | 2596 | ||
2177 | idx = 0; | 2597 | idx = 0; |
2178 | dataq = &phwi_context->be_def_dataq; | 2598 | dataq = &phwi_context->be_def_dataq; |
2179 | cq = &phwi_context->be_cq; | 2599 | cq = &phwi_context->be_cq[0]; |
2180 | mem = &dataq->dma_mem; | 2600 | mem = &dataq->dma_mem; |
2181 | mem_descr = phba->init_mem; | 2601 | mem_descr = phba->init_mem; |
2182 | mem_descr += HWI_MEM_ASYNC_DATA_RING; | 2602 | mem_descr += HWI_MEM_ASYNC_DATA_RING; |
@@ -2239,6 +2659,30 @@ beiscsi_post_pages(struct beiscsi_hba *phba) | |||
2239 | return 0; | 2659 | return 0; |
2240 | } | 2660 | } |
2241 | 2661 | ||
2662 | static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q) | ||
2663 | { | ||
2664 | struct be_dma_mem *mem = &q->dma_mem; | ||
2665 | if (mem->va) | ||
2666 | pci_free_consistent(phba->pcidev, mem->size, | ||
2667 | mem->va, mem->dma); | ||
2668 | } | ||
2669 | |||
2670 | static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, | ||
2671 | u16 len, u16 entry_size) | ||
2672 | { | ||
2673 | struct be_dma_mem *mem = &q->dma_mem; | ||
2674 | |||
2675 | memset(q, 0, sizeof(*q)); | ||
2676 | q->len = len; | ||
2677 | q->entry_size = entry_size; | ||
2678 | mem->size = len * entry_size; | ||
2679 | mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma); | ||
2680 | if (!mem->va) | ||
2681 | return -1; | ||
2682 | memset(mem->va, 0, mem->size); | ||
2683 | return 0; | ||
2684 | } | ||
2685 | |||
2242 | static int | 2686 | static int |
2243 | beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | 2687 | beiscsi_create_wrb_rings(struct beiscsi_hba *phba, |
2244 | struct hwi_context_memory *phwi_context, | 2688 | struct hwi_context_memory *phwi_context, |
@@ -2308,7 +2752,8 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
2308 | "wrbq create failed."); | 2752 | "wrbq create failed."); |
2309 | return status; | 2753 | return status; |
2310 | } | 2754 | } |
2311 | phwi_ctrlr->wrb_context[i].cid = phwi_context->be_wrbq[i].id; | 2755 | phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i]. |
2756 | id; | ||
2312 | } | 2757 | } |
2313 | kfree(pwrb_arr); | 2758 | kfree(pwrb_arr); |
2314 | return 0; | 2759 | return 0; |
@@ -2328,13 +2773,29 @@ static void free_wrb_handles(struct beiscsi_hba *phba) | |||
2328 | } | 2773 | } |
2329 | } | 2774 | } |
2330 | 2775 | ||
2776 | static void be_mcc_queues_destroy(struct beiscsi_hba *phba) | ||
2777 | { | ||
2778 | struct be_queue_info *q; | ||
2779 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2780 | |||
2781 | q = &phba->ctrl.mcc_obj.q; | ||
2782 | if (q->created) | ||
2783 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); | ||
2784 | be_queue_free(phba, q); | ||
2785 | |||
2786 | q = &phba->ctrl.mcc_obj.cq; | ||
2787 | if (q->created) | ||
2788 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
2789 | be_queue_free(phba, q); | ||
2790 | } | ||
2791 | |||
2331 | static void hwi_cleanup(struct beiscsi_hba *phba) | 2792 | static void hwi_cleanup(struct beiscsi_hba *phba) |
2332 | { | 2793 | { |
2333 | struct be_queue_info *q; | 2794 | struct be_queue_info *q; |
2334 | struct be_ctrl_info *ctrl = &phba->ctrl; | 2795 | struct be_ctrl_info *ctrl = &phba->ctrl; |
2335 | struct hwi_controller *phwi_ctrlr; | 2796 | struct hwi_controller *phwi_ctrlr; |
2336 | struct hwi_context_memory *phwi_context; | 2797 | struct hwi_context_memory *phwi_context; |
2337 | int i; | 2798 | int i, eq_num; |
2338 | 2799 | ||
2339 | phwi_ctrlr = phba->phwi_ctrlr; | 2800 | phwi_ctrlr = phba->phwi_ctrlr; |
2340 | phwi_context = phwi_ctrlr->phwi_ctxt; | 2801 | phwi_context = phwi_ctrlr->phwi_ctxt; |
@@ -2343,7 +2804,6 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
2343 | if (q->created) | 2804 | if (q->created) |
2344 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); | 2805 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); |
2345 | } | 2806 | } |
2346 | |||
2347 | free_wrb_handles(phba); | 2807 | free_wrb_handles(phba); |
2348 | 2808 | ||
2349 | q = &phwi_context->be_def_hdrq; | 2809 | q = &phwi_context->be_def_hdrq; |
@@ -2356,13 +2816,76 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
2356 | 2816 | ||
2357 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | 2817 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); |
2358 | 2818 | ||
2359 | q = &phwi_context->be_cq; | 2819 | for (i = 0; i < (phba->num_cpus); i++) { |
2360 | if (q->created) | 2820 | q = &phwi_context->be_cq[i]; |
2361 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | 2821 | if (q->created) |
2822 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
2823 | } | ||
2824 | if (phba->msix_enabled) | ||
2825 | eq_num = 1; | ||
2826 | else | ||
2827 | eq_num = 0; | ||
2828 | for (i = 0; i < (phba->num_cpus + eq_num); i++) { | ||
2829 | q = &phwi_context->be_eq[i].q; | ||
2830 | if (q->created) | ||
2831 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | ||
2832 | } | ||
2833 | be_mcc_queues_destroy(phba); | ||
2834 | } | ||
2362 | 2835 | ||
2363 | q = &phwi_context->be_eq.q; | 2836 | static int be_mcc_queues_create(struct beiscsi_hba *phba, |
2364 | if (q->created) | 2837 | struct hwi_context_memory *phwi_context) |
2365 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | 2838 | { |
2839 | struct be_queue_info *q, *cq; | ||
2840 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2841 | |||
2842 | /* Alloc MCC compl queue */ | ||
2843 | cq = &phba->ctrl.mcc_obj.cq; | ||
2844 | if (be_queue_alloc(phba, cq, MCC_CQ_LEN, | ||
2845 | sizeof(struct be_mcc_compl))) | ||
2846 | goto err; | ||
2847 | /* Ask BE to create MCC compl queue; */ | ||
2848 | if (phba->msix_enabled) { | ||
2849 | if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq | ||
2850 | [phba->num_cpus].q, false, true, 0)) | ||
2851 | goto mcc_cq_free; | ||
2852 | } else { | ||
2853 | if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq[0].q, | ||
2854 | false, true, 0)) | ||
2855 | goto mcc_cq_free; | ||
2856 | } | ||
2857 | |||
2858 | /* Alloc MCC queue */ | ||
2859 | q = &phba->ctrl.mcc_obj.q; | ||
2860 | if (be_queue_alloc(phba, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) | ||
2861 | goto mcc_cq_destroy; | ||
2862 | |||
2863 | /* Ask BE to create MCC queue */ | ||
2864 | if (beiscsi_cmd_mccq_create(phba, q, cq)) | ||
2865 | goto mcc_q_free; | ||
2866 | |||
2867 | return 0; | ||
2868 | |||
2869 | mcc_q_free: | ||
2870 | be_queue_free(phba, q); | ||
2871 | mcc_cq_destroy: | ||
2872 | beiscsi_cmd_q_destroy(ctrl, cq, QTYPE_CQ); | ||
2873 | mcc_cq_free: | ||
2874 | be_queue_free(phba, cq); | ||
2875 | err: | ||
2876 | return -1; | ||
2877 | } | ||
2878 | |||
2879 | static int find_num_cpus(void) | ||
2880 | { | ||
2881 | int num_cpus = 0; | ||
2882 | |||
2883 | num_cpus = num_online_cpus(); | ||
2884 | if (num_cpus >= MAX_CPUS) | ||
2885 | num_cpus = MAX_CPUS - 1; | ||
2886 | |||
2887 | SE_DEBUG(DBG_LVL_8, "num_cpus = %d \n", num_cpus); | ||
2888 | return num_cpus; | ||
2366 | } | 2889 | } |
2367 | 2890 | ||
2368 | static int hwi_init_port(struct beiscsi_hba *phba) | 2891 | static int hwi_init_port(struct beiscsi_hba *phba) |
@@ -2376,34 +2899,30 @@ static int hwi_init_port(struct beiscsi_hba *phba) | |||
2376 | def_pdu_ring_sz = | 2899 | def_pdu_ring_sz = |
2377 | phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr); | 2900 | phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr); |
2378 | phwi_ctrlr = phba->phwi_ctrlr; | 2901 | phwi_ctrlr = phba->phwi_ctrlr; |
2379 | |||
2380 | phwi_context = phwi_ctrlr->phwi_ctxt; | 2902 | phwi_context = phwi_ctrlr->phwi_ctxt; |
2381 | phwi_context->be_eq.max_eqd = 0; | 2903 | phwi_context->max_eqd = 0; |
2382 | phwi_context->be_eq.min_eqd = 0; | 2904 | phwi_context->min_eqd = 0; |
2383 | phwi_context->be_eq.cur_eqd = 64; | 2905 | phwi_context->cur_eqd = 64; |
2384 | phwi_context->be_eq.enable_aic = false; | ||
2385 | be_cmd_fw_initialize(&phba->ctrl); | 2906 | be_cmd_fw_initialize(&phba->ctrl); |
2386 | status = beiscsi_create_eq(phba, phwi_context); | 2907 | |
2908 | status = beiscsi_create_eqs(phba, phwi_context); | ||
2387 | if (status != 0) { | 2909 | if (status != 0) { |
2388 | shost_printk(KERN_ERR, phba->shost, "EQ not created \n"); | 2910 | shost_printk(KERN_ERR, phba->shost, "EQ not created \n"); |
2389 | goto error; | 2911 | goto error; |
2390 | } | 2912 | } |
2391 | 2913 | ||
2392 | status = mgmt_check_supported_fw(ctrl); | 2914 | status = be_mcc_queues_create(phba, phwi_context); |
2393 | if (status != 0) { | 2915 | if (status != 0) |
2394 | shost_printk(KERN_ERR, phba->shost, | ||
2395 | "Unsupported fw version \n"); | ||
2396 | goto error; | 2916 | goto error; |
2397 | } | ||
2398 | 2917 | ||
2399 | status = mgmt_get_fw_config(ctrl, phba); | 2918 | status = mgmt_check_supported_fw(ctrl, phba); |
2400 | if (status != 0) { | 2919 | if (status != 0) { |
2401 | shost_printk(KERN_ERR, phba->shost, | 2920 | shost_printk(KERN_ERR, phba->shost, |
2402 | "Error getting fw config\n"); | 2921 | "Unsupported fw version \n"); |
2403 | goto error; | 2922 | goto error; |
2404 | } | 2923 | } |
2405 | 2924 | ||
2406 | status = beiscsi_create_cq(phba, phwi_context); | 2925 | status = beiscsi_create_cqs(phba, phwi_context); |
2407 | if (status != 0) { | 2926 | if (status != 0) { |
2408 | shost_printk(KERN_ERR, phba->shost, "CQ not created\n"); | 2927 | shost_printk(KERN_ERR, phba->shost, "CQ not created\n"); |
2409 | goto error; | 2928 | goto error; |
@@ -2447,7 +2966,6 @@ error: | |||
2447 | return -ENOMEM; | 2966 | return -ENOMEM; |
2448 | } | 2967 | } |
2449 | 2968 | ||
2450 | |||
2451 | static int hwi_init_controller(struct beiscsi_hba *phba) | 2969 | static int hwi_init_controller(struct beiscsi_hba *phba) |
2452 | { | 2970 | { |
2453 | struct hwi_controller *phwi_ctrlr; | 2971 | struct hwi_controller *phwi_ctrlr; |
@@ -2530,6 +3048,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
2530 | 3048 | ||
2531 | phba->io_sgl_hndl_avbl = 0; | 3049 | phba->io_sgl_hndl_avbl = 0; |
2532 | phba->eh_sgl_hndl_avbl = 0; | 3050 | phba->eh_sgl_hndl_avbl = 0; |
3051 | |||
2533 | mem_descr_sglh = phba->init_mem; | 3052 | mem_descr_sglh = phba->init_mem; |
2534 | mem_descr_sglh += HWI_MEM_SGLH; | 3053 | mem_descr_sglh += HWI_MEM_SGLH; |
2535 | if (1 == mem_descr_sglh->num_elements) { | 3054 | if (1 == mem_descr_sglh->num_elements) { |
@@ -2608,7 +3127,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
2608 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); | 3127 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); |
2609 | pfrag += phba->params.num_sge_per_io; | 3128 | pfrag += phba->params.num_sge_per_io; |
2610 | psgl_handle->sgl_index = | 3129 | psgl_handle->sgl_index = |
2611 | phba->fw_config.iscsi_cid_start + arr_index++; | 3130 | phba->fw_config.iscsi_icd_start + arr_index++; |
2612 | } | 3131 | } |
2613 | idx++; | 3132 | idx++; |
2614 | } | 3133 | } |
@@ -2623,7 +3142,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
2623 | { | 3142 | { |
2624 | int i, new_cid; | 3143 | int i, new_cid; |
2625 | 3144 | ||
2626 | phba->cid_array = kmalloc(sizeof(void *) * phba->params.cxns_per_ctrl, | 3145 | phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, |
2627 | GFP_KERNEL); | 3146 | GFP_KERNEL); |
2628 | if (!phba->cid_array) { | 3147 | if (!phba->cid_array) { |
2629 | shost_printk(KERN_ERR, phba->shost, | 3148 | shost_printk(KERN_ERR, phba->shost, |
@@ -2631,7 +3150,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
2631 | "hba_setup_cid_tbls\n"); | 3150 | "hba_setup_cid_tbls\n"); |
2632 | return -ENOMEM; | 3151 | return -ENOMEM; |
2633 | } | 3152 | } |
2634 | phba->ep_array = kmalloc(sizeof(struct iscsi_endpoint *) * | 3153 | phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * |
2635 | phba->params.cxns_per_ctrl * 2, GFP_KERNEL); | 3154 | phba->params.cxns_per_ctrl * 2, GFP_KERNEL); |
2636 | if (!phba->ep_array) { | 3155 | if (!phba->ep_array) { |
2637 | shost_printk(KERN_ERR, phba->shost, | 3156 | shost_printk(KERN_ERR, phba->shost, |
@@ -2640,7 +3159,7 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
2640 | kfree(phba->cid_array); | 3159 | kfree(phba->cid_array); |
2641 | return -ENOMEM; | 3160 | return -ENOMEM; |
2642 | } | 3161 | } |
2643 | new_cid = phba->fw_config.iscsi_icd_start; | 3162 | new_cid = phba->fw_config.iscsi_cid_start; |
2644 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | 3163 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { |
2645 | phba->cid_array[i] = new_cid; | 3164 | phba->cid_array[i] = new_cid; |
2646 | new_cid += 2; | 3165 | new_cid += 2; |
@@ -2656,13 +3175,12 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) | |||
2656 | struct hwi_context_memory *phwi_context; | 3175 | struct hwi_context_memory *phwi_context; |
2657 | struct be_queue_info *eq; | 3176 | struct be_queue_info *eq; |
2658 | u8 __iomem *addr; | 3177 | u8 __iomem *addr; |
2659 | u32 reg; | 3178 | u32 reg, i; |
2660 | u32 enabled; | 3179 | u32 enabled; |
2661 | 3180 | ||
2662 | phwi_ctrlr = phba->phwi_ctrlr; | 3181 | phwi_ctrlr = phba->phwi_ctrlr; |
2663 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3182 | phwi_context = phwi_ctrlr->phwi_ctxt; |
2664 | 3183 | ||
2665 | eq = &phwi_context->be_eq.q; | ||
2666 | addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg + | 3184 | addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg + |
2667 | PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); | 3185 | PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); |
2668 | reg = ioread32(addr); | 3186 | reg = ioread32(addr); |
@@ -2673,12 +3191,18 @@ static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) | |||
2673 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 3191 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
2674 | SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); | 3192 | SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); |
2675 | iowrite32(reg, addr); | 3193 | iowrite32(reg, addr); |
2676 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); | 3194 | if (!phba->msix_enabled) { |
2677 | 3195 | eq = &phwi_context->be_eq[0].q; | |
2678 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); | 3196 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); |
2679 | } else | 3197 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); |
2680 | shost_printk(KERN_WARNING, phba->shost, | 3198 | } else { |
2681 | "In hwi_enable_intr, Not Enabled \n"); | 3199 | for (i = 0; i <= phba->num_cpus; i++) { |
3200 | eq = &phwi_context->be_eq[i].q; | ||
3201 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); | ||
3202 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); | ||
3203 | } | ||
3204 | } | ||
3205 | } | ||
2682 | return true; | 3206 | return true; |
2683 | } | 3207 | } |
2684 | 3208 | ||
@@ -2738,17 +3262,30 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) | |||
2738 | struct hwi_context_memory *phwi_context; | 3262 | struct hwi_context_memory *phwi_context; |
2739 | struct be_queue_info *eq; | 3263 | struct be_queue_info *eq; |
2740 | struct be_eq_entry *eqe = NULL; | 3264 | struct be_eq_entry *eqe = NULL; |
3265 | int i, eq_msix; | ||
3266 | unsigned int num_processed; | ||
2741 | 3267 | ||
2742 | phwi_ctrlr = phba->phwi_ctrlr; | 3268 | phwi_ctrlr = phba->phwi_ctrlr; |
2743 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3269 | phwi_context = phwi_ctrlr->phwi_ctxt; |
2744 | eq = &phwi_context->be_eq.q; | 3270 | if (phba->msix_enabled) |
2745 | eqe = queue_tail_node(eq); | 3271 | eq_msix = 1; |
3272 | else | ||
3273 | eq_msix = 0; | ||
2746 | 3274 | ||
2747 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 3275 | for (i = 0; i < (phba->num_cpus + eq_msix); i++) { |
2748 | & EQE_VALID_MASK) { | 3276 | eq = &phwi_context->be_eq[i].q; |
2749 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
2750 | queue_tail_inc(eq); | ||
2751 | eqe = queue_tail_node(eq); | 3277 | eqe = queue_tail_node(eq); |
3278 | num_processed = 0; | ||
3279 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
3280 | & EQE_VALID_MASK) { | ||
3281 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
3282 | queue_tail_inc(eq); | ||
3283 | eqe = queue_tail_node(eq); | ||
3284 | num_processed++; | ||
3285 | } | ||
3286 | |||
3287 | if (num_processed) | ||
3288 | hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1); | ||
2752 | } | 3289 | } |
2753 | } | 3290 | } |
2754 | 3291 | ||
@@ -2760,8 +3297,9 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) | |||
2760 | if (mgmt_status) | 3297 | if (mgmt_status) |
2761 | shost_printk(KERN_WARNING, phba->shost, | 3298 | shost_printk(KERN_WARNING, phba->shost, |
2762 | "mgmt_epfw_cleanup FAILED \n"); | 3299 | "mgmt_epfw_cleanup FAILED \n"); |
2763 | hwi_cleanup(phba); | 3300 | |
2764 | hwi_purge_eq(phba); | 3301 | hwi_purge_eq(phba); |
3302 | hwi_cleanup(phba); | ||
2765 | kfree(phba->io_sgl_hndl_base); | 3303 | kfree(phba->io_sgl_hndl_base); |
2766 | kfree(phba->eh_sgl_hndl_base); | 3304 | kfree(phba->eh_sgl_hndl_base); |
2767 | kfree(phba->cid_array); | 3305 | kfree(phba->cid_array); |
@@ -2782,7 +3320,8 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | |||
2782 | * We can always use 0 here because it is reserved by libiscsi for | 3320 | * We can always use 0 here because it is reserved by libiscsi for |
2783 | * login/startup related tasks. | 3321 | * login/startup related tasks. |
2784 | */ | 3322 | */ |
2785 | pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid, 0); | 3323 | pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid - |
3324 | phba->fw_config.iscsi_cid_start)); | ||
2786 | pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb; | 3325 | pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb; |
2787 | memset(pwrb, 0, sizeof(*pwrb)); | 3326 | memset(pwrb, 0, sizeof(*pwrb)); |
2788 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | 3327 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, |
@@ -2846,8 +3385,8 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | |||
2846 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb)); | 3385 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb)); |
2847 | 3386 | ||
2848 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; | 3387 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; |
2849 | doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) << | 3388 | doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) |
2850 | DB_DEF_PDU_WRB_INDEX_SHIFT; | 3389 | << DB_DEF_PDU_WRB_INDEX_SHIFT; |
2851 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 3390 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
2852 | 3391 | ||
2853 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | 3392 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); |
@@ -2856,7 +3395,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | |||
2856 | static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, | 3395 | static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, |
2857 | int *index, int *age) | 3396 | int *index, int *age) |
2858 | { | 3397 | { |
2859 | *index = be32_to_cpu(itt) >> 16; | 3398 | *index = (int)itt; |
2860 | if (age) | 3399 | if (age) |
2861 | *age = conn->session->age; | 3400 | *age = conn->session->age; |
2862 | } | 3401 | } |
@@ -2885,15 +3424,14 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
2885 | 3424 | ||
2886 | io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, | 3425 | io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, |
2887 | GFP_KERNEL, &paddr); | 3426 | GFP_KERNEL, &paddr); |
2888 | |||
2889 | if (!io_task->cmd_bhs) | 3427 | if (!io_task->cmd_bhs) |
2890 | return -ENOMEM; | 3428 | return -ENOMEM; |
2891 | |||
2892 | io_task->bhs_pa.u.a64.address = paddr; | 3429 | io_task->bhs_pa.u.a64.address = paddr; |
3430 | io_task->libiscsi_itt = (itt_t)task->itt; | ||
2893 | io_task->pwrb_handle = alloc_wrb_handle(phba, | 3431 | io_task->pwrb_handle = alloc_wrb_handle(phba, |
2894 | beiscsi_conn->beiscsi_conn_cid, | 3432 | beiscsi_conn->beiscsi_conn_cid - |
2895 | task->itt); | 3433 | phba->fw_config.iscsi_cid_start |
2896 | io_task->pwrb_handle->pio_handle = task; | 3434 | ); |
2897 | io_task->conn = beiscsi_conn; | 3435 | io_task->conn = beiscsi_conn; |
2898 | 3436 | ||
2899 | task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr; | 3437 | task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr; |
@@ -2905,10 +3443,9 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
2905 | spin_unlock(&phba->io_sgl_lock); | 3443 | spin_unlock(&phba->io_sgl_lock); |
2906 | if (!io_task->psgl_handle) | 3444 | if (!io_task->psgl_handle) |
2907 | goto free_hndls; | 3445 | goto free_hndls; |
2908 | |||
2909 | } else { | 3446 | } else { |
2910 | io_task->scsi_cmnd = NULL; | 3447 | io_task->scsi_cmnd = NULL; |
2911 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { | 3448 | if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { |
2912 | if (!beiscsi_conn->login_in_progress) { | 3449 | if (!beiscsi_conn->login_in_progress) { |
2913 | spin_lock(&phba->mgmt_sgl_lock); | 3450 | spin_lock(&phba->mgmt_sgl_lock); |
2914 | io_task->psgl_handle = (struct sgl_handle *) | 3451 | io_task->psgl_handle = (struct sgl_handle *) |
@@ -2932,14 +3469,19 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
2932 | goto free_hndls; | 3469 | goto free_hndls; |
2933 | } | 3470 | } |
2934 | } | 3471 | } |
2935 | itt = (itt_t) cpu_to_be32(((unsigned int)task->itt << 16) | | 3472 | itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle-> |
2936 | (unsigned int)(io_task->psgl_handle->sgl_index)); | 3473 | wrb_index << 16) | (unsigned int) |
3474 | (io_task->psgl_handle->sgl_index)); | ||
3475 | io_task->pwrb_handle->pio_handle = task; | ||
3476 | |||
2937 | io_task->cmd_bhs->iscsi_hdr.itt = itt; | 3477 | io_task->cmd_bhs->iscsi_hdr.itt = itt; |
2938 | return 0; | 3478 | return 0; |
2939 | 3479 | ||
2940 | free_hndls: | 3480 | free_hndls: |
2941 | phwi_ctrlr = phba->phwi_ctrlr; | 3481 | phwi_ctrlr = phba->phwi_ctrlr; |
2942 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid]; | 3482 | pwrb_context = &phwi_ctrlr->wrb_context[ |
3483 | beiscsi_conn->beiscsi_conn_cid - | ||
3484 | phba->fw_config.iscsi_cid_start]; | ||
2943 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | 3485 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); |
2944 | io_task->pwrb_handle = NULL; | 3486 | io_task->pwrb_handle = NULL; |
2945 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, | 3487 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, |
@@ -2959,7 +3501,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) | |||
2959 | struct hwi_controller *phwi_ctrlr; | 3501 | struct hwi_controller *phwi_ctrlr; |
2960 | 3502 | ||
2961 | phwi_ctrlr = phba->phwi_ctrlr; | 3503 | phwi_ctrlr = phba->phwi_ctrlr; |
2962 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid]; | 3504 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid |
3505 | - phba->fw_config.iscsi_cid_start]; | ||
2963 | if (io_task->pwrb_handle) { | 3506 | if (io_task->pwrb_handle) { |
2964 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | 3507 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); |
2965 | io_task->pwrb_handle = NULL; | 3508 | io_task->pwrb_handle = NULL; |
@@ -3006,7 +3549,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | |||
3006 | io_task->bhs_len = sizeof(struct be_cmd_bhs); | 3549 | io_task->bhs_len = sizeof(struct be_cmd_bhs); |
3007 | 3550 | ||
3008 | if (writedir) { | 3551 | if (writedir) { |
3009 | SE_DEBUG(DBG_LVL_4, " WRITE Command \t"); | ||
3010 | memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48); | 3552 | memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48); |
3011 | AMAP_SET_BITS(struct amap_pdu_data_out, itt, | 3553 | AMAP_SET_BITS(struct amap_pdu_data_out, itt, |
3012 | &io_task->cmd_bhs->iscsi_data_pdu, | 3554 | &io_task->cmd_bhs->iscsi_data_pdu, |
@@ -3016,11 +3558,12 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | |||
3016 | ISCSI_OPCODE_SCSI_DATA_OUT); | 3558 | ISCSI_OPCODE_SCSI_DATA_OUT); |
3017 | AMAP_SET_BITS(struct amap_pdu_data_out, final_bit, | 3559 | AMAP_SET_BITS(struct amap_pdu_data_out, final_bit, |
3018 | &io_task->cmd_bhs->iscsi_data_pdu, 1); | 3560 | &io_task->cmd_bhs->iscsi_data_pdu, 1); |
3019 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD); | 3561 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3562 | INI_WR_CMD); | ||
3020 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); | 3563 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); |
3021 | } else { | 3564 | } else { |
3022 | SE_DEBUG(DBG_LVL_4, "READ Command \t"); | 3565 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3023 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD); | 3566 | INI_RD_CMD); |
3024 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); | 3567 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); |
3025 | } | 3568 | } |
3026 | memcpy(&io_task->cmd_bhs->iscsi_data_pdu. | 3569 | memcpy(&io_task->cmd_bhs->iscsi_data_pdu. |
@@ -3055,15 +3598,17 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | |||
3055 | 3598 | ||
3056 | static int beiscsi_mtask(struct iscsi_task *task) | 3599 | static int beiscsi_mtask(struct iscsi_task *task) |
3057 | { | 3600 | { |
3058 | struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data; | 3601 | struct beiscsi_io_task *io_task = task->dd_data; |
3059 | struct iscsi_conn *conn = task->conn; | 3602 | struct iscsi_conn *conn = task->conn; |
3060 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 3603 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
3061 | struct beiscsi_hba *phba = beiscsi_conn->phba; | 3604 | struct beiscsi_hba *phba = beiscsi_conn->phba; |
3062 | struct iscsi_wrb *pwrb = NULL; | 3605 | struct iscsi_wrb *pwrb = NULL; |
3063 | unsigned int doorbell = 0; | 3606 | unsigned int doorbell = 0; |
3064 | struct iscsi_task *aborted_task; | 3607 | unsigned int cid; |
3065 | 3608 | ||
3609 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
3066 | pwrb = io_task->pwrb_handle->pwrb; | 3610 | pwrb = io_task->pwrb_handle->pwrb; |
3611 | memset(pwrb, 0, sizeof(*pwrb)); | ||
3067 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, | 3612 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, |
3068 | be32_to_cpu(task->cmdsn)); | 3613 | be32_to_cpu(task->cmdsn)); |
3069 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, | 3614 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, |
@@ -3073,40 +3618,37 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3073 | 3618 | ||
3074 | switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { | 3619 | switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { |
3075 | case ISCSI_OP_LOGIN: | 3620 | case ISCSI_OP_LOGIN: |
3076 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, TGT_DM_CMD); | 3621 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3622 | TGT_DM_CMD); | ||
3077 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3623 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
3078 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); | 3624 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); |
3079 | hwi_write_buffer(pwrb, task); | 3625 | hwi_write_buffer(pwrb, task); |
3080 | break; | 3626 | break; |
3081 | case ISCSI_OP_NOOP_OUT: | 3627 | case ISCSI_OP_NOOP_OUT: |
3082 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD); | 3628 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3629 | INI_RD_CMD); | ||
3630 | if (task->hdr->ttt == ISCSI_RESERVED_TAG) | ||
3631 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | ||
3632 | else | ||
3633 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1); | ||
3083 | hwi_write_buffer(pwrb, task); | 3634 | hwi_write_buffer(pwrb, task); |
3084 | break; | 3635 | break; |
3085 | case ISCSI_OP_TEXT: | 3636 | case ISCSI_OP_TEXT: |
3086 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD); | 3637 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3087 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); | 3638 | TGT_DM_CMD); |
3639 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | ||
3088 | hwi_write_buffer(pwrb, task); | 3640 | hwi_write_buffer(pwrb, task); |
3089 | break; | 3641 | break; |
3090 | case ISCSI_OP_SCSI_TMFUNC: | 3642 | case ISCSI_OP_SCSI_TMFUNC: |
3091 | aborted_task = iscsi_itt_to_task(conn, | 3643 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3092 | ((struct iscsi_tm *)task->hdr)->rtt); | 3644 | INI_TMF_CMD); |
3093 | if (!aborted_task) | ||
3094 | return 0; | ||
3095 | aborted_io_task = aborted_task->dd_data; | ||
3096 | if (!aborted_io_task->scsi_cmnd) | ||
3097 | return 0; | ||
3098 | |||
3099 | mgmt_invalidate_icds(phba, | ||
3100 | aborted_io_task->psgl_handle->sgl_index, | ||
3101 | beiscsi_conn->beiscsi_conn_cid); | ||
3102 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD); | ||
3103 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3645 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
3104 | hwi_write_buffer(pwrb, task); | 3646 | hwi_write_buffer(pwrb, task); |
3105 | break; | 3647 | break; |
3106 | case ISCSI_OP_LOGOUT: | 3648 | case ISCSI_OP_LOGOUT: |
3107 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | 3649 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); |
3108 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, | 3650 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, |
3109 | HWH_TYPE_LOGOUT); | 3651 | HWH_TYPE_LOGOUT); |
3110 | hwi_write_buffer(pwrb, task); | 3652 | hwi_write_buffer(pwrb, task); |
3111 | break; | 3653 | break; |
3112 | 3654 | ||
@@ -3117,12 +3659,12 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3117 | } | 3659 | } |
3118 | 3660 | ||
3119 | AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, | 3661 | AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, |
3120 | be32_to_cpu(task->data_count)); | 3662 | task->data_count); |
3121 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, | 3663 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, |
3122 | io_task->pwrb_handle->nxt_wrb_index); | 3664 | io_task->pwrb_handle->nxt_wrb_index); |
3123 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); | 3665 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); |
3124 | 3666 | ||
3125 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; | 3667 | doorbell |= cid & DB_WRB_POST_CID_MASK; |
3126 | doorbell |= (io_task->pwrb_handle->wrb_index & | 3668 | doorbell |= (io_task->pwrb_handle->wrb_index & |
3127 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; | 3669 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; |
3128 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 3670 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
@@ -3132,17 +3674,12 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
3132 | 3674 | ||
3133 | static int beiscsi_task_xmit(struct iscsi_task *task) | 3675 | static int beiscsi_task_xmit(struct iscsi_task *task) |
3134 | { | 3676 | { |
3135 | struct iscsi_conn *conn = task->conn; | ||
3136 | struct beiscsi_io_task *io_task = task->dd_data; | 3677 | struct beiscsi_io_task *io_task = task->dd_data; |
3137 | struct scsi_cmnd *sc = task->sc; | 3678 | struct scsi_cmnd *sc = task->sc; |
3138 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
3139 | struct scatterlist *sg; | 3679 | struct scatterlist *sg; |
3140 | int num_sg; | 3680 | int num_sg; |
3141 | unsigned int writedir = 0, xferlen = 0; | 3681 | unsigned int writedir = 0, xferlen = 0; |
3142 | 3682 | ||
3143 | SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t" | ||
3144 | "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid, | ||
3145 | task, conn, beiscsi_conn); | ||
3146 | if (!sc) | 3683 | if (!sc) |
3147 | return beiscsi_mtask(task); | 3684 | return beiscsi_mtask(task); |
3148 | 3685 | ||
@@ -3168,6 +3705,10 @@ static int beiscsi_task_xmit(struct iscsi_task *task) | |||
3168 | static void beiscsi_remove(struct pci_dev *pcidev) | 3705 | static void beiscsi_remove(struct pci_dev *pcidev) |
3169 | { | 3706 | { |
3170 | struct beiscsi_hba *phba = NULL; | 3707 | struct beiscsi_hba *phba = NULL; |
3708 | struct hwi_controller *phwi_ctrlr; | ||
3709 | struct hwi_context_memory *phwi_context; | ||
3710 | struct be_eq_obj *pbe_eq; | ||
3711 | unsigned int i, msix_vec; | ||
3171 | 3712 | ||
3172 | phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); | 3713 | phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); |
3173 | if (!phba) { | 3714 | if (!phba) { |
@@ -3175,12 +3716,24 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
3175 | return; | 3716 | return; |
3176 | } | 3717 | } |
3177 | 3718 | ||
3719 | phwi_ctrlr = phba->phwi_ctrlr; | ||
3720 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
3178 | hwi_disable_intr(phba); | 3721 | hwi_disable_intr(phba); |
3179 | if (phba->pcidev->irq) | 3722 | if (phba->msix_enabled) { |
3180 | free_irq(phba->pcidev->irq, phba); | 3723 | for (i = 0; i <= phba->num_cpus; i++) { |
3724 | msix_vec = phba->msix_entries[i].vector; | ||
3725 | free_irq(msix_vec, &phwi_context->be_eq[i]); | ||
3726 | } | ||
3727 | } else | ||
3728 | if (phba->pcidev->irq) | ||
3729 | free_irq(phba->pcidev->irq, phba); | ||
3730 | pci_disable_msix(phba->pcidev); | ||
3181 | destroy_workqueue(phba->wq); | 3731 | destroy_workqueue(phba->wq); |
3182 | if (blk_iopoll_enabled) | 3732 | if (blk_iopoll_enabled) |
3183 | blk_iopoll_disable(&phba->iopoll); | 3733 | for (i = 0; i < phba->num_cpus; i++) { |
3734 | pbe_eq = &phwi_context->be_eq[i]; | ||
3735 | blk_iopoll_disable(&pbe_eq->iopoll); | ||
3736 | } | ||
3184 | 3737 | ||
3185 | beiscsi_clean_port(phba); | 3738 | beiscsi_clean_port(phba); |
3186 | beiscsi_free_mem(phba); | 3739 | beiscsi_free_mem(phba); |
@@ -3194,11 +3747,29 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
3194 | iscsi_host_free(phba->shost); | 3747 | iscsi_host_free(phba->shost); |
3195 | } | 3748 | } |
3196 | 3749 | ||
3750 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | ||
3751 | { | ||
3752 | int i, status; | ||
3753 | |||
3754 | for (i = 0; i <= phba->num_cpus; i++) | ||
3755 | phba->msix_entries[i].entry = i; | ||
3756 | |||
3757 | status = pci_enable_msix(phba->pcidev, phba->msix_entries, | ||
3758 | (phba->num_cpus + 1)); | ||
3759 | if (!status) | ||
3760 | phba->msix_enabled = true; | ||
3761 | |||
3762 | return; | ||
3763 | } | ||
3764 | |||
3197 | static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | 3765 | static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, |
3198 | const struct pci_device_id *id) | 3766 | const struct pci_device_id *id) |
3199 | { | 3767 | { |
3200 | struct beiscsi_hba *phba = NULL; | 3768 | struct beiscsi_hba *phba = NULL; |
3201 | int ret; | 3769 | struct hwi_controller *phwi_ctrlr; |
3770 | struct hwi_context_memory *phwi_context; | ||
3771 | struct be_eq_obj *pbe_eq; | ||
3772 | int ret, msix_vec, num_cpus, i; | ||
3202 | 3773 | ||
3203 | ret = beiscsi_enable_pci(pcidev); | 3774 | ret = beiscsi_enable_pci(pcidev); |
3204 | if (ret < 0) { | 3775 | if (ret < 0) { |
@@ -3214,7 +3785,29 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3214 | goto disable_pci; | 3785 | goto disable_pci; |
3215 | } | 3786 | } |
3216 | 3787 | ||
3217 | pci_set_drvdata(pcidev, phba); | 3788 | switch (pcidev->device) { |
3789 | case BE_DEVICE_ID1: | ||
3790 | case OC_DEVICE_ID1: | ||
3791 | case OC_DEVICE_ID2: | ||
3792 | phba->generation = BE_GEN2; | ||
3793 | break; | ||
3794 | case BE_DEVICE_ID2: | ||
3795 | case OC_DEVICE_ID3: | ||
3796 | phba->generation = BE_GEN3; | ||
3797 | break; | ||
3798 | default: | ||
3799 | phba->generation = 0; | ||
3800 | } | ||
3801 | |||
3802 | if (enable_msix) | ||
3803 | num_cpus = find_num_cpus(); | ||
3804 | else | ||
3805 | num_cpus = 1; | ||
3806 | phba->num_cpus = num_cpus; | ||
3807 | SE_DEBUG(DBG_LVL_8, "num_cpus = %d \n", phba->num_cpus); | ||
3808 | |||
3809 | if (enable_msix) | ||
3810 | beiscsi_msix_enable(phba); | ||
3218 | ret = be_ctrl_init(phba, pcidev); | 3811 | ret = be_ctrl_init(phba, pcidev); |
3219 | if (ret) { | 3812 | if (ret) { |
3220 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | 3813 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" |
@@ -3225,7 +3818,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3225 | spin_lock_init(&phba->io_sgl_lock); | 3818 | spin_lock_init(&phba->io_sgl_lock); |
3226 | spin_lock_init(&phba->mgmt_sgl_lock); | 3819 | spin_lock_init(&phba->mgmt_sgl_lock); |
3227 | spin_lock_init(&phba->isr_lock); | 3820 | spin_lock_init(&phba->isr_lock); |
3821 | ret = mgmt_get_fw_config(&phba->ctrl, phba); | ||
3822 | if (ret != 0) { | ||
3823 | shost_printk(KERN_ERR, phba->shost, | ||
3824 | "Error getting fw config\n"); | ||
3825 | goto free_port; | ||
3826 | } | ||
3827 | phba->shost->max_id = phba->fw_config.iscsi_cid_count; | ||
3228 | beiscsi_get_params(phba); | 3828 | beiscsi_get_params(phba); |
3829 | phba->shost->can_queue = phba->params.ios_per_ctrl; | ||
3229 | ret = beiscsi_init_port(phba); | 3830 | ret = beiscsi_init_port(phba); |
3230 | if (ret < 0) { | 3831 | if (ret < 0) { |
3231 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | 3832 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" |
@@ -3233,9 +3834,18 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3233 | goto free_port; | 3834 | goto free_port; |
3234 | } | 3835 | } |
3235 | 3836 | ||
3837 | for (i = 0; i < MAX_MCC_CMD ; i++) { | ||
3838 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
3839 | phba->ctrl.mcc_tag[i] = i + 1; | ||
3840 | phba->ctrl.mcc_numtag[i + 1] = 0; | ||
3841 | phba->ctrl.mcc_tag_available++; | ||
3842 | } | ||
3843 | |||
3844 | phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; | ||
3845 | |||
3236 | snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", | 3846 | snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", |
3237 | phba->shost->host_no); | 3847 | phba->shost->host_no); |
3238 | phba->wq = create_singlethread_workqueue(phba->wq_name); | 3848 | phba->wq = create_workqueue(phba->wq_name); |
3239 | if (!phba->wq) { | 3849 | if (!phba->wq) { |
3240 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | 3850 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" |
3241 | "Failed to allocate work queue\n"); | 3851 | "Failed to allocate work queue\n"); |
@@ -3244,11 +3854,16 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3244 | 3854 | ||
3245 | INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs); | 3855 | INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs); |
3246 | 3856 | ||
3857 | phwi_ctrlr = phba->phwi_ctrlr; | ||
3858 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
3247 | if (blk_iopoll_enabled) { | 3859 | if (blk_iopoll_enabled) { |
3248 | blk_iopoll_init(&phba->iopoll, be_iopoll_budget, be_iopoll); | 3860 | for (i = 0; i < phba->num_cpus; i++) { |
3249 | blk_iopoll_enable(&phba->iopoll); | 3861 | pbe_eq = &phwi_context->be_eq[i]; |
3862 | blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, | ||
3863 | be_iopoll); | ||
3864 | blk_iopoll_enable(&pbe_eq->iopoll); | ||
3865 | } | ||
3250 | } | 3866 | } |
3251 | |||
3252 | ret = beiscsi_init_irqs(phba); | 3867 | ret = beiscsi_init_irqs(phba); |
3253 | if (ret < 0) { | 3868 | if (ret < 0) { |
3254 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | 3869 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" |
@@ -3261,17 +3876,26 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
3261 | "Failed to hwi_enable_intr\n"); | 3876 | "Failed to hwi_enable_intr\n"); |
3262 | goto free_ctrlr; | 3877 | goto free_ctrlr; |
3263 | } | 3878 | } |
3264 | |||
3265 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n"); | 3879 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n"); |
3266 | return 0; | 3880 | return 0; |
3267 | 3881 | ||
3268 | free_ctrlr: | 3882 | free_ctrlr: |
3269 | if (phba->pcidev->irq) | 3883 | if (phba->msix_enabled) { |
3270 | free_irq(phba->pcidev->irq, phba); | 3884 | for (i = 0; i <= phba->num_cpus; i++) { |
3885 | msix_vec = phba->msix_entries[i].vector; | ||
3886 | free_irq(msix_vec, &phwi_context->be_eq[i]); | ||
3887 | } | ||
3888 | } else | ||
3889 | if (phba->pcidev->irq) | ||
3890 | free_irq(phba->pcidev->irq, phba); | ||
3891 | pci_disable_msix(phba->pcidev); | ||
3271 | free_blkenbld: | 3892 | free_blkenbld: |
3272 | destroy_workqueue(phba->wq); | 3893 | destroy_workqueue(phba->wq); |
3273 | if (blk_iopoll_enabled) | 3894 | if (blk_iopoll_enabled) |
3274 | blk_iopoll_disable(&phba->iopoll); | 3895 | for (i = 0; i < phba->num_cpus; i++) { |
3896 | pbe_eq = &phwi_context->be_eq[i]; | ||
3897 | blk_iopoll_disable(&pbe_eq->iopoll); | ||
3898 | } | ||
3275 | free_twq: | 3899 | free_twq: |
3276 | beiscsi_clean_port(phba); | 3900 | beiscsi_clean_port(phba); |
3277 | beiscsi_free_mem(phba); | 3901 | beiscsi_free_mem(phba); |
@@ -3293,7 +3917,7 @@ disable_pci: | |||
3293 | struct iscsi_transport beiscsi_iscsi_transport = { | 3917 | struct iscsi_transport beiscsi_iscsi_transport = { |
3294 | .owner = THIS_MODULE, | 3918 | .owner = THIS_MODULE, |
3295 | .name = DRV_NAME, | 3919 | .name = DRV_NAME, |
3296 | .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | | 3920 | .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO | |
3297 | CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, | 3921 | CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, |
3298 | .param_mask = ISCSI_MAX_RECV_DLENGTH | | 3922 | .param_mask = ISCSI_MAX_RECV_DLENGTH | |
3299 | ISCSI_MAX_XMIT_DLENGTH | | 3923 | ISCSI_MAX_XMIT_DLENGTH | |
@@ -3351,6 +3975,7 @@ static struct pci_driver beiscsi_pci_driver = { | |||
3351 | .id_table = beiscsi_pci_id_table | 3975 | .id_table = beiscsi_pci_id_table |
3352 | }; | 3976 | }; |
3353 | 3977 | ||
3978 | |||
3354 | static int __init beiscsi_module_init(void) | 3979 | static int __init beiscsi_module_init(void) |
3355 | { | 3980 | { |
3356 | int ret; | 3981 | int ret; |
@@ -3361,7 +3986,7 @@ static int __init beiscsi_module_init(void) | |||
3361 | SE_DEBUG(DBG_LVL_1, | 3986 | SE_DEBUG(DBG_LVL_1, |
3362 | "beiscsi_module_init - Unable to register beiscsi" | 3987 | "beiscsi_module_init - Unable to register beiscsi" |
3363 | "transport.\n"); | 3988 | "transport.\n"); |
3364 | ret = -ENOMEM; | 3989 | return -ENOMEM; |
3365 | } | 3990 | } |
3366 | SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n", | 3991 | SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n", |
3367 | &beiscsi_iscsi_transport); | 3992 | &beiscsi_iscsi_transport); |
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 53c9b70ac7ac..87ec21280a37 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -21,11 +21,9 @@ | |||
21 | #ifndef _BEISCSI_MAIN_ | 21 | #ifndef _BEISCSI_MAIN_ |
22 | #define _BEISCSI_MAIN_ | 22 | #define _BEISCSI_MAIN_ |
23 | 23 | ||
24 | |||
25 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
26 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
27 | #include <linux/in.h> | 26 | #include <linux/in.h> |
28 | #include <linux/blk-iopoll.h> | ||
29 | #include <scsi/scsi.h> | 27 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_cmnd.h> | 28 | #include <scsi/scsi_cmnd.h> |
31 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
@@ -35,39 +33,36 @@ | |||
35 | #include <scsi/scsi_transport_iscsi.h> | 33 | #include <scsi/scsi_transport_iscsi.h> |
36 | 34 | ||
37 | #include "be.h" | 35 | #include "be.h" |
38 | |||
39 | |||
40 | |||
41 | #define DRV_NAME "be2iscsi" | 36 | #define DRV_NAME "be2iscsi" |
42 | #define BUILD_STR "2.0.527.0" | 37 | #define BUILD_STR "2.0.527.0" |
43 | |||
44 | #define BE_NAME "ServerEngines BladeEngine2" \ | 38 | #define BE_NAME "ServerEngines BladeEngine2" \ |
45 | "Linux iSCSI Driver version" BUILD_STR | 39 | "Linux iSCSI Driver version" BUILD_STR |
46 | #define DRV_DESC BE_NAME " " "Driver" | 40 | #define DRV_DESC BE_NAME " " "Driver" |
47 | 41 | ||
48 | #define BE_VENDOR_ID 0x19A2 | 42 | #define BE_VENDOR_ID 0x19A2 |
43 | /* DEVICE ID's for BE2 */ | ||
49 | #define BE_DEVICE_ID1 0x212 | 44 | #define BE_DEVICE_ID1 0x212 |
50 | #define OC_DEVICE_ID1 0x702 | 45 | #define OC_DEVICE_ID1 0x702 |
51 | #define OC_DEVICE_ID2 0x703 | 46 | #define OC_DEVICE_ID2 0x703 |
52 | 47 | ||
53 | #define BE2_MAX_SESSIONS 64 | 48 | /* DEVICE ID's for BE3 */ |
49 | #define BE_DEVICE_ID2 0x222 | ||
50 | #define OC_DEVICE_ID3 0x712 | ||
51 | |||
52 | #define BE2_IO_DEPTH 1024 | ||
53 | #define BE2_MAX_SESSIONS 256 | ||
54 | #define BE2_CMDS_PER_CXN 128 | 54 | #define BE2_CMDS_PER_CXN 128 |
55 | #define BE2_LOGOUTS BE2_MAX_SESSIONS | ||
56 | #define BE2_TMFS 16 | 55 | #define BE2_TMFS 16 |
57 | #define BE2_NOPOUT_REQ 16 | 56 | #define BE2_NOPOUT_REQ 16 |
58 | #define BE2_ASYNCPDUS BE2_MAX_SESSIONS | ||
59 | #define BE2_MAX_ICDS 2048 | ||
60 | #define BE2_SGE 32 | 57 | #define BE2_SGE 32 |
61 | #define BE2_DEFPDU_HDR_SZ 64 | 58 | #define BE2_DEFPDU_HDR_SZ 64 |
62 | #define BE2_DEFPDU_DATA_SZ 8192 | 59 | #define BE2_DEFPDU_DATA_SZ 8192 |
63 | #define BE2_IO_DEPTH \ | ||
64 | (BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ)) | ||
65 | 60 | ||
66 | #define BEISCSI_SGLIST_ELEMENTS BE2_SGE | 61 | #define MAX_CPUS 31 |
62 | #define BEISCSI_SGLIST_ELEMENTS 30 | ||
67 | 63 | ||
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 */ | 64 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ |
70 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ | 65 | #define BEISCSI_MAX_SECTORS 256 /* scsi_host->max_sectors */ |
71 | 66 | ||
72 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | 67 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
73 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ | 68 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ |
@@ -79,7 +74,7 @@ | |||
79 | #define BE_SENSE_INFO_SIZE 258 | 74 | #define BE_SENSE_INFO_SIZE 258 |
80 | #define BE_ISCSI_PDU_HEADER_SIZE 64 | 75 | #define BE_ISCSI_PDU_HEADER_SIZE 64 |
81 | #define BE_MIN_MEM_SIZE 16384 | 76 | #define BE_MIN_MEM_SIZE 16384 |
82 | 77 | #define MAX_CMD_SZ 65536 | |
83 | #define IIOC_SCSI_DATA 0x05 /* Write Operation */ | 78 | #define IIOC_SCSI_DATA 0x05 /* Write Operation */ |
84 | 79 | ||
85 | #define DBG_LVL 0x00000001 | 80 | #define DBG_LVL 0x00000001 |
@@ -100,6 +95,8 @@ do { \ | |||
100 | } \ | 95 | } \ |
101 | } while (0); | 96 | } while (0); |
102 | 97 | ||
98 | #define BE_ADAPTER_UP 0x00000000 | ||
99 | #define BE_ADAPTER_LINK_DOWN 0x00000001 | ||
103 | /** | 100 | /** |
104 | * hardware needs the async PDU buffers to be posted in multiples of 8 | 101 | * hardware needs the async PDU buffers to be posted in multiples of 8 |
105 | * So have atleast 8 of them by default | 102 | * So have atleast 8 of them by default |
@@ -160,21 +157,19 @@ do { \ | |||
160 | 157 | ||
161 | enum be_mem_enum { | 158 | enum be_mem_enum { |
162 | HWI_MEM_ADDN_CONTEXT, | 159 | HWI_MEM_ADDN_CONTEXT, |
163 | HWI_MEM_CQ, | ||
164 | HWI_MEM_EQ, | ||
165 | HWI_MEM_WRB, | 160 | HWI_MEM_WRB, |
166 | HWI_MEM_WRBH, | 161 | HWI_MEM_WRBH, |
167 | HWI_MEM_SGLH, /* 5 */ | 162 | HWI_MEM_SGLH, |
168 | HWI_MEM_SGE, | 163 | HWI_MEM_SGE, |
169 | HWI_MEM_ASYNC_HEADER_BUF, | 164 | HWI_MEM_ASYNC_HEADER_BUF, /* 5 */ |
170 | HWI_MEM_ASYNC_DATA_BUF, | 165 | HWI_MEM_ASYNC_DATA_BUF, |
171 | HWI_MEM_ASYNC_HEADER_RING, | 166 | HWI_MEM_ASYNC_HEADER_RING, |
172 | HWI_MEM_ASYNC_DATA_RING, /* 10 */ | 167 | HWI_MEM_ASYNC_DATA_RING, |
173 | HWI_MEM_ASYNC_HEADER_HANDLE, | 168 | HWI_MEM_ASYNC_HEADER_HANDLE, |
174 | HWI_MEM_ASYNC_DATA_HANDLE, | 169 | HWI_MEM_ASYNC_DATA_HANDLE, /* 10 */ |
175 | HWI_MEM_ASYNC_PDU_CONTEXT, | 170 | HWI_MEM_ASYNC_PDU_CONTEXT, |
176 | ISCSI_MEM_GLOBAL_HEADER, | 171 | ISCSI_MEM_GLOBAL_HEADER, |
177 | SE_MEM_MAX /* 15 */ | 172 | SE_MEM_MAX |
178 | }; | 173 | }; |
179 | 174 | ||
180 | struct be_bus_address32 { | 175 | struct be_bus_address32 { |
@@ -212,6 +207,9 @@ struct be_mem_descriptor { | |||
212 | 207 | ||
213 | struct sgl_handle { | 208 | struct sgl_handle { |
214 | unsigned int sgl_index; | 209 | unsigned int sgl_index; |
210 | unsigned int type; | ||
211 | unsigned int cid; | ||
212 | struct iscsi_task *task; | ||
215 | struct iscsi_sge *pfrag; | 213 | struct iscsi_sge *pfrag; |
216 | }; | 214 | }; |
217 | 215 | ||
@@ -259,6 +257,11 @@ struct hba_parameters { | |||
259 | unsigned int num_sge; | 257 | unsigned int num_sge; |
260 | }; | 258 | }; |
261 | 259 | ||
260 | struct invalidate_command_table { | ||
261 | unsigned short icd; | ||
262 | unsigned short cid; | ||
263 | } __packed; | ||
264 | |||
262 | struct beiscsi_hba { | 265 | struct beiscsi_hba { |
263 | struct hba_parameters params; | 266 | struct hba_parameters params; |
264 | struct hwi_controller *phwi_ctrlr; | 267 | struct hwi_controller *phwi_ctrlr; |
@@ -274,13 +277,17 @@ struct beiscsi_hba { | |||
274 | struct pci_dev *pcidev; | 277 | struct pci_dev *pcidev; |
275 | unsigned int state; | 278 | unsigned int state; |
276 | unsigned short asic_revision; | 279 | unsigned short asic_revision; |
277 | struct blk_iopoll iopoll; | 280 | unsigned int num_cpus; |
281 | unsigned int nxt_cqid; | ||
282 | struct msix_entry msix_entries[MAX_CPUS + 1]; | ||
283 | bool msix_enabled; | ||
278 | struct be_mem_descriptor *init_mem; | 284 | struct be_mem_descriptor *init_mem; |
279 | 285 | ||
280 | unsigned short io_sgl_alloc_index; | 286 | unsigned short io_sgl_alloc_index; |
281 | unsigned short io_sgl_free_index; | 287 | unsigned short io_sgl_free_index; |
282 | unsigned short io_sgl_hndl_avbl; | 288 | unsigned short io_sgl_hndl_avbl; |
283 | struct sgl_handle **io_sgl_hndl_base; | 289 | struct sgl_handle **io_sgl_hndl_base; |
290 | struct sgl_handle **sgl_hndl_array; | ||
284 | 291 | ||
285 | unsigned short eh_sgl_alloc_index; | 292 | unsigned short eh_sgl_alloc_index; |
286 | unsigned short eh_sgl_free_index; | 293 | unsigned short eh_sgl_free_index; |
@@ -315,6 +322,7 @@ struct beiscsi_hba { | |||
315 | unsigned short cid_alloc; | 322 | unsigned short cid_alloc; |
316 | unsigned short cid_free; | 323 | unsigned short cid_free; |
317 | unsigned short avlbl_cids; | 324 | unsigned short avlbl_cids; |
325 | unsigned short iscsi_features; | ||
318 | spinlock_t cid_lock; | 326 | spinlock_t cid_lock; |
319 | } fw_config; | 327 | } fw_config; |
320 | 328 | ||
@@ -325,6 +333,9 @@ struct beiscsi_hba { | |||
325 | struct workqueue_struct *wq; /* The actuak work queue */ | 333 | struct workqueue_struct *wq; /* The actuak work queue */ |
326 | struct work_struct work_cqs; /* The work being queued */ | 334 | struct work_struct work_cqs; /* The work being queued */ |
327 | struct be_ctrl_info ctrl; | 335 | struct be_ctrl_info ctrl; |
336 | unsigned int generation; | ||
337 | struct invalidate_command_table inv_tbl[128]; | ||
338 | |||
328 | }; | 339 | }; |
329 | 340 | ||
330 | struct beiscsi_session { | 341 | struct beiscsi_session { |
@@ -343,6 +354,7 @@ struct beiscsi_conn { | |||
343 | unsigned short login_in_progress; | 354 | unsigned short login_in_progress; |
344 | struct sgl_handle *plogin_sgl_handle; | 355 | struct sgl_handle *plogin_sgl_handle; |
345 | struct beiscsi_session *beiscsi_sess; | 356 | struct beiscsi_session *beiscsi_sess; |
357 | struct iscsi_task *task; | ||
346 | }; | 358 | }; |
347 | 359 | ||
348 | /* This structure is used by the chip */ | 360 | /* This structure is used by the chip */ |
@@ -390,7 +402,7 @@ struct beiscsi_io_task { | |||
390 | unsigned int flags; | 402 | unsigned int flags; |
391 | unsigned short cid; | 403 | unsigned short cid; |
392 | unsigned short header_len; | 404 | unsigned short header_len; |
393 | 405 | itt_t libiscsi_itt; | |
394 | struct be_cmd_bhs *cmd_bhs; | 406 | struct be_cmd_bhs *cmd_bhs; |
395 | struct be_bus_address bhs_pa; | 407 | struct be_bus_address bhs_pa; |
396 | unsigned short bhs_len; | 408 | unsigned short bhs_len; |
@@ -486,8 +498,6 @@ struct hwi_async_entry { | |||
486 | struct list_head data_busy_list; | 498 | struct list_head data_busy_list; |
487 | }; | 499 | }; |
488 | 500 | ||
489 | #define BE_MIN_ASYNC_ENTRIES 128 | ||
490 | |||
491 | struct hwi_async_pdu_context { | 501 | struct hwi_async_pdu_context { |
492 | struct { | 502 | struct { |
493 | struct be_bus_address pa_base; | 503 | struct be_bus_address pa_base; |
@@ -528,7 +538,7 @@ struct hwi_async_pdu_context { | |||
528 | * This is a varying size list! Do not add anything | 538 | * This is a varying size list! Do not add anything |
529 | * after this entry!! | 539 | * after this entry!! |
530 | */ | 540 | */ |
531 | struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES]; | 541 | struct hwi_async_entry async_entry[BE2_MAX_SESSIONS * 2]; |
532 | }; | 542 | }; |
533 | 543 | ||
534 | #define PDUCQE_CODE_MASK 0x0000003F | 544 | #define PDUCQE_CODE_MASK 0x0000003F |
@@ -599,7 +609,6 @@ struct amap_cq_db { | |||
599 | 609 | ||
600 | void beiscsi_process_eq(struct beiscsi_hba *phba); | 610 | void beiscsi_process_eq(struct beiscsi_hba *phba); |
601 | 611 | ||
602 | |||
603 | struct iscsi_wrb { | 612 | struct iscsi_wrb { |
604 | u32 dw[16]; | 613 | u32 dw[16]; |
605 | } __packed; | 614 | } __packed; |
@@ -651,11 +660,12 @@ struct amap_iscsi_wrb { | |||
651 | 660 | ||
652 | } __packed; | 661 | } __packed; |
653 | 662 | ||
654 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, | 663 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid); |
655 | int index); | ||
656 | void | 664 | void |
657 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); | 665 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); |
658 | 666 | ||
667 | void beiscsi_process_all_cqs(struct work_struct *work); | ||
668 | |||
659 | struct pdu_nop_out { | 669 | struct pdu_nop_out { |
660 | u32 dw[12]; | 670 | u32 dw[12]; |
661 | }; | 671 | }; |
@@ -797,7 +807,6 @@ struct hwi_controller { | |||
797 | struct be_ring default_pdu_hdr; | 807 | struct be_ring default_pdu_hdr; |
798 | struct be_ring default_pdu_data; | 808 | struct be_ring default_pdu_data; |
799 | struct hwi_context_memory *phwi_ctxt; | 809 | struct hwi_context_memory *phwi_ctxt; |
800 | unsigned short cq_errors[CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN]; | ||
801 | }; | 810 | }; |
802 | 811 | ||
803 | enum hwh_type_enum { | 812 | enum hwh_type_enum { |
@@ -820,10 +829,12 @@ struct wrb_handle { | |||
820 | }; | 829 | }; |
821 | 830 | ||
822 | struct hwi_context_memory { | 831 | struct hwi_context_memory { |
823 | struct be_eq_obj be_eq; | 832 | /* Adaptive interrupt coalescing (AIC) info */ |
824 | struct be_queue_info be_cq; | 833 | u16 min_eqd; /* in usecs */ |
825 | struct be_queue_info be_mcc_cq; | 834 | u16 max_eqd; /* in usecs */ |
826 | struct be_queue_info be_mcc; | 835 | u16 cur_eqd; /* in usecs */ |
836 | struct be_eq_obj be_eq[MAX_CPUS]; | ||
837 | struct be_queue_info be_cq[MAX_CPUS]; | ||
827 | 838 | ||
828 | struct be_queue_info be_def_hdrq; | 839 | struct be_queue_info be_def_hdrq; |
829 | struct be_queue_info be_def_dataq; | 840 | struct be_queue_info be_def_dataq; |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 12e644fc746e..e641922f20bc 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -35,7 +35,6 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, | |||
35 | 35 | ||
36 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 36 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
37 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); | 37 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); |
38 | |||
39 | status = be_mbox_notify(ctrl); | 38 | status = be_mbox_notify(ctrl); |
40 | if (!status) { | 39 | if (!status) { |
41 | struct be_fw_cfg *pfw_cfg; | 40 | struct be_fw_cfg *pfw_cfg; |
@@ -49,6 +48,14 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, | |||
49 | pfw_cfg->ulp[0].sq_base; | 48 | pfw_cfg->ulp[0].sq_base; |
50 | phba->fw_config.iscsi_cid_count = | 49 | phba->fw_config.iscsi_cid_count = |
51 | pfw_cfg->ulp[0].sq_count; | 50 | pfw_cfg->ulp[0].sq_count; |
51 | if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { | ||
52 | SE_DEBUG(DBG_LVL_8, | ||
53 | "FW reported MAX CXNS as %d \t" | ||
54 | "Max Supported = %d.\n", | ||
55 | phba->fw_config.iscsi_cid_count, | ||
56 | BE2_MAX_SESSIONS); | ||
57 | phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2; | ||
58 | } | ||
52 | } else { | 59 | } else { |
53 | shost_printk(KERN_WARNING, phba->shost, | 60 | shost_printk(KERN_WARNING, phba->shost, |
54 | "Failed in mgmt_get_fw_config \n"); | 61 | "Failed in mgmt_get_fw_config \n"); |
@@ -58,7 +65,8 @@ unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, | |||
58 | return status; | 65 | return status; |
59 | } | 66 | } |
60 | 67 | ||
61 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl) | 68 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl, |
69 | struct beiscsi_hba *phba) | ||
62 | { | 70 | { |
63 | struct be_dma_mem nonemb_cmd; | 71 | struct be_dma_mem nonemb_cmd; |
64 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 72 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
@@ -77,6 +85,7 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl) | |||
77 | } | 85 | } |
78 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); | 86 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); |
79 | req = nonemb_cmd.va; | 87 | req = nonemb_cmd.va; |
88 | memset(req, 0, sizeof(*req)); | ||
80 | spin_lock(&ctrl->mbox_lock); | 89 | spin_lock(&ctrl->mbox_lock); |
81 | memset(wrb, 0, sizeof(*wrb)); | 90 | memset(wrb, 0, sizeof(*wrb)); |
82 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | 91 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); |
@@ -85,7 +94,6 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl) | |||
85 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | 94 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); |
86 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | 95 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); |
87 | sge->len = cpu_to_le32(nonemb_cmd.size); | 96 | sge->len = cpu_to_le32(nonemb_cmd.size); |
88 | |||
89 | status = be_mbox_notify(ctrl); | 97 | status = be_mbox_notify(ctrl); |
90 | if (!status) { | 98 | if (!status) { |
91 | struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; | 99 | struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; |
@@ -95,21 +103,25 @@ unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl) | |||
95 | resp->params.hba_attribs.firmware_version_string); | 103 | resp->params.hba_attribs.firmware_version_string); |
96 | SE_DEBUG(DBG_LVL_8, | 104 | SE_DEBUG(DBG_LVL_8, |
97 | "Developer Build, not performing version check...\n"); | 105 | "Developer Build, not performing version check...\n"); |
98 | 106 | phba->fw_config.iscsi_features = | |
107 | resp->params.hba_attribs.iscsi_features; | ||
108 | SE_DEBUG(DBG_LVL_8, " phba->fw_config.iscsi_features = %d\n", | ||
109 | phba->fw_config.iscsi_features); | ||
99 | } else | 110 | } else |
100 | SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); | 111 | SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); |
112 | spin_unlock(&ctrl->mbox_lock); | ||
101 | if (nonemb_cmd.va) | 113 | if (nonemb_cmd.va) |
102 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | 114 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, |
103 | nonemb_cmd.va, nonemb_cmd.dma); | 115 | nonemb_cmd.va, nonemb_cmd.dma); |
104 | 116 | ||
105 | spin_unlock(&ctrl->mbox_lock); | ||
106 | return status; | 117 | return status; |
107 | } | 118 | } |
108 | 119 | ||
120 | |||
109 | unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | 121 | unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) |
110 | { | 122 | { |
111 | struct be_ctrl_info *ctrl = &phba->ctrl; | 123 | struct be_ctrl_info *ctrl = &phba->ctrl; |
112 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 124 | struct be_mcc_wrb *wrb = wrb_from_mccq(phba); |
113 | struct iscsi_cleanup_req *req = embedded_payload(wrb); | 125 | struct iscsi_cleanup_req *req = embedded_payload(wrb); |
114 | int status = 0; | 126 | int status = 0; |
115 | 127 | ||
@@ -124,7 +136,7 @@ unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | |||
124 | req->hdr_ring_id = 0; | 136 | req->hdr_ring_id = 0; |
125 | req->data_ring_id = 0; | 137 | req->data_ring_id = 0; |
126 | 138 | ||
127 | status = be_mbox_notify(ctrl); | 139 | status = be_mcc_notify_wait(phba); |
128 | if (status) | 140 | if (status) |
129 | shost_printk(KERN_WARNING, phba->shost, | 141 | shost_printk(KERN_WARNING, phba->shost, |
130 | " mgmt_epfw_cleanup , FAILED\n"); | 142 | " mgmt_epfw_cleanup , FAILED\n"); |
@@ -133,14 +145,22 @@ unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | |||
133 | } | 145 | } |
134 | 146 | ||
135 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | 147 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, |
136 | unsigned int icd, unsigned int cid) | 148 | struct invalidate_command_table *inv_tbl, |
149 | unsigned int num_invalidate, unsigned int cid) | ||
137 | { | 150 | { |
138 | struct be_dma_mem nonemb_cmd; | 151 | struct be_dma_mem nonemb_cmd; |
139 | struct be_ctrl_info *ctrl = &phba->ctrl; | 152 | struct be_ctrl_info *ctrl = &phba->ctrl; |
140 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 153 | struct be_mcc_wrb *wrb; |
141 | struct be_sge *sge = nonembedded_sgl(wrb); | 154 | struct be_sge *sge; |
142 | struct invalidate_commands_params_in *req; | 155 | struct invalidate_commands_params_in *req; |
143 | int status = 0; | 156 | unsigned int i, tag = 0; |
157 | |||
158 | spin_lock(&ctrl->mbox_lock); | ||
159 | tag = alloc_mcc_tag(phba); | ||
160 | if (!tag) { | ||
161 | spin_unlock(&ctrl->mbox_lock); | ||
162 | return tag; | ||
163 | } | ||
144 | 164 | ||
145 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, | 165 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, |
146 | sizeof(struct invalidate_commands_params_in), | 166 | sizeof(struct invalidate_commands_params_in), |
@@ -149,12 +169,15 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | |||
149 | SE_DEBUG(DBG_LVL_1, | 169 | SE_DEBUG(DBG_LVL_1, |
150 | "Failed to allocate memory for" | 170 | "Failed to allocate memory for" |
151 | "mgmt_invalidate_icds \n"); | 171 | "mgmt_invalidate_icds \n"); |
172 | spin_unlock(&ctrl->mbox_lock); | ||
152 | return -1; | 173 | return -1; |
153 | } | 174 | } |
154 | nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); | 175 | nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); |
155 | req = nonemb_cmd.va; | 176 | req = nonemb_cmd.va; |
156 | spin_lock(&ctrl->mbox_lock); | 177 | memset(req, 0, sizeof(*req)); |
157 | memset(wrb, 0, sizeof(*wrb)); | 178 | wrb = wrb_from_mccq(phba); |
179 | sge = nonembedded_sgl(wrb); | ||
180 | wrb->tag0 |= tag; | ||
158 | 181 | ||
159 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | 182 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); |
160 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 183 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
@@ -162,21 +185,22 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | |||
162 | sizeof(*req)); | 185 | sizeof(*req)); |
163 | req->ref_handle = 0; | 186 | req->ref_handle = 0; |
164 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | 187 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; |
165 | req->icd_count = 0; | 188 | for (i = 0; i < num_invalidate; i++) { |
166 | req->table[req->icd_count].icd = icd; | 189 | req->table[i].icd = inv_tbl->icd; |
167 | req->table[req->icd_count].cid = cid; | 190 | req->table[i].cid = inv_tbl->cid; |
191 | req->icd_count++; | ||
192 | inv_tbl++; | ||
193 | } | ||
168 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | 194 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); |
169 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | 195 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); |
170 | sge->len = cpu_to_le32(nonemb_cmd.size); | 196 | sge->len = cpu_to_le32(nonemb_cmd.size); |
171 | 197 | ||
172 | status = be_mbox_notify(ctrl); | 198 | be_mcc_notify(phba); |
173 | if (status) | ||
174 | SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n"); | ||
175 | spin_unlock(&ctrl->mbox_lock); | 199 | spin_unlock(&ctrl->mbox_lock); |
176 | if (nonemb_cmd.va) | 200 | if (nonemb_cmd.va) |
177 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | 201 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, |
178 | nonemb_cmd.va, nonemb_cmd.dma); | 202 | nonemb_cmd.va, nonemb_cmd.dma); |
179 | return status; | 203 | return tag; |
180 | } | 204 | } |
181 | 205 | ||
182 | unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | 206 | unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, |
@@ -186,13 +210,19 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | |||
186 | unsigned short savecfg_flag) | 210 | unsigned short savecfg_flag) |
187 | { | 211 | { |
188 | struct be_ctrl_info *ctrl = &phba->ctrl; | 212 | struct be_ctrl_info *ctrl = &phba->ctrl; |
189 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 213 | struct be_mcc_wrb *wrb; |
190 | struct iscsi_invalidate_connection_params_in *req = | 214 | struct iscsi_invalidate_connection_params_in *req; |
191 | embedded_payload(wrb); | 215 | unsigned int tag = 0; |
192 | int status = 0; | ||
193 | 216 | ||
194 | spin_lock(&ctrl->mbox_lock); | 217 | spin_lock(&ctrl->mbox_lock); |
195 | memset(wrb, 0, sizeof(*wrb)); | 218 | tag = alloc_mcc_tag(phba); |
219 | if (!tag) { | ||
220 | spin_unlock(&ctrl->mbox_lock); | ||
221 | return tag; | ||
222 | } | ||
223 | wrb = wrb_from_mccq(phba); | ||
224 | wrb->tag0 |= tag; | ||
225 | req = embedded_payload(wrb); | ||
196 | 226 | ||
197 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 227 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
198 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | 228 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, |
@@ -205,35 +235,37 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | |||
205 | else | 235 | else |
206 | req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; | 236 | req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; |
207 | req->save_cfg = savecfg_flag; | 237 | req->save_cfg = savecfg_flag; |
208 | status = be_mbox_notify(ctrl); | 238 | be_mcc_notify(phba); |
209 | if (status) | ||
210 | SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n"); | ||
211 | |||
212 | spin_unlock(&ctrl->mbox_lock); | 239 | spin_unlock(&ctrl->mbox_lock); |
213 | return status; | 240 | return tag; |
214 | } | 241 | } |
215 | 242 | ||
216 | unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, | 243 | unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, |
217 | unsigned short cid, unsigned int upload_flag) | 244 | unsigned short cid, unsigned int upload_flag) |
218 | { | 245 | { |
219 | struct be_ctrl_info *ctrl = &phba->ctrl; | 246 | struct be_ctrl_info *ctrl = &phba->ctrl; |
220 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 247 | struct be_mcc_wrb *wrb; |
221 | struct tcp_upload_params_in *req = embedded_payload(wrb); | 248 | struct tcp_upload_params_in *req; |
222 | int status = 0; | 249 | unsigned int tag = 0; |
223 | 250 | ||
224 | spin_lock(&ctrl->mbox_lock); | 251 | spin_lock(&ctrl->mbox_lock); |
225 | memset(wrb, 0, sizeof(*wrb)); | 252 | tag = alloc_mcc_tag(phba); |
253 | if (!tag) { | ||
254 | spin_unlock(&ctrl->mbox_lock); | ||
255 | return tag; | ||
256 | } | ||
257 | wrb = wrb_from_mccq(phba); | ||
258 | req = embedded_payload(wrb); | ||
259 | wrb->tag0 |= tag; | ||
226 | 260 | ||
227 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 261 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
228 | be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, | 262 | be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, |
229 | OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); | 263 | OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); |
230 | req->id = (unsigned short)cid; | 264 | req->id = (unsigned short)cid; |
231 | req->upload_type = (unsigned char)upload_flag; | 265 | req->upload_type = (unsigned char)upload_flag; |
232 | status = be_mbox_notify(ctrl); | 266 | be_mcc_notify(phba); |
233 | if (status) | ||
234 | SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n"); | ||
235 | spin_unlock(&ctrl->mbox_lock); | 267 | spin_unlock(&ctrl->mbox_lock); |
236 | return status; | 268 | return tag; |
237 | } | 269 | } |
238 | 270 | ||
239 | int mgmt_open_connection(struct beiscsi_hba *phba, | 271 | int mgmt_open_connection(struct beiscsi_hba *phba, |
@@ -245,13 +277,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba, | |||
245 | struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; | 277 | struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; |
246 | struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; | 278 | struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; |
247 | struct be_ctrl_info *ctrl = &phba->ctrl; | 279 | struct be_ctrl_info *ctrl = &phba->ctrl; |
248 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 280 | struct be_mcc_wrb *wrb; |
249 | struct tcp_connect_and_offload_in *req = embedded_payload(wrb); | 281 | struct tcp_connect_and_offload_in *req; |
250 | unsigned short def_hdr_id; | 282 | unsigned short def_hdr_id; |
251 | unsigned short def_data_id; | 283 | unsigned short def_data_id; |
252 | struct phys_addr template_address = { 0, 0 }; | 284 | struct phys_addr template_address = { 0, 0 }; |
253 | struct phys_addr *ptemplate_address; | 285 | struct phys_addr *ptemplate_address; |
254 | int status = 0; | 286 | unsigned int tag = 0; |
287 | unsigned int i; | ||
255 | unsigned short cid = beiscsi_ep->ep_cid; | 288 | unsigned short cid = beiscsi_ep->ep_cid; |
256 | 289 | ||
257 | phwi_ctrlr = phba->phwi_ctrlr; | 290 | phwi_ctrlr = phba->phwi_ctrlr; |
@@ -262,7 +295,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba, | |||
262 | ptemplate_address = &template_address; | 295 | ptemplate_address = &template_address; |
263 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); | 296 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); |
264 | spin_lock(&ctrl->mbox_lock); | 297 | spin_lock(&ctrl->mbox_lock); |
265 | memset(wrb, 0, sizeof(*wrb)); | 298 | tag = alloc_mcc_tag(phba); |
299 | if (!tag) { | ||
300 | spin_unlock(&ctrl->mbox_lock); | ||
301 | return tag; | ||
302 | } | ||
303 | wrb = wrb_from_mccq(phba); | ||
304 | req = embedded_payload(wrb); | ||
305 | wrb->tag0 |= tag; | ||
266 | 306 | ||
267 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 307 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
268 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 308 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
@@ -296,26 +336,47 @@ int mgmt_open_connection(struct beiscsi_hba *phba, | |||
296 | 336 | ||
297 | } | 337 | } |
298 | req->cid = cid; | 338 | req->cid = cid; |
299 | req->cq_id = phwi_context->be_cq.id; | 339 | i = phba->nxt_cqid++; |
340 | if (phba->nxt_cqid == phba->num_cpus) | ||
341 | phba->nxt_cqid = 0; | ||
342 | req->cq_id = phwi_context->be_cq[i].id; | ||
343 | SE_DEBUG(DBG_LVL_8, "i=%d cq_id=%d \n", i, req->cq_id); | ||
300 | req->defq_id = def_hdr_id; | 344 | req->defq_id = def_hdr_id; |
301 | req->hdr_ring_id = def_hdr_id; | 345 | req->hdr_ring_id = def_hdr_id; |
302 | req->data_ring_id = def_data_id; | 346 | req->data_ring_id = def_data_id; |
303 | req->do_offload = 1; | 347 | req->do_offload = 1; |
304 | req->dataout_template_pa.lo = ptemplate_address->lo; | 348 | req->dataout_template_pa.lo = ptemplate_address->lo; |
305 | req->dataout_template_pa.hi = ptemplate_address->hi; | 349 | req->dataout_template_pa.hi = ptemplate_address->hi; |
306 | status = be_mbox_notify(ctrl); | 350 | be_mcc_notify(phba); |
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); | 351 | spin_unlock(&ctrl->mbox_lock); |
320 | return status; | 352 | return tag; |
321 | } | 353 | } |
354 | |||
355 | unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba) | ||
356 | { | ||
357 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
358 | struct be_mcc_wrb *wrb; | ||
359 | struct be_cmd_req_get_mac_addr *req; | ||
360 | unsigned int tag = 0; | ||
361 | |||
362 | SE_DEBUG(DBG_LVL_8, "In be_cmd_get_mac_addr\n"); | ||
363 | spin_lock(&ctrl->mbox_lock); | ||
364 | tag = alloc_mcc_tag(phba); | ||
365 | if (!tag) { | ||
366 | spin_unlock(&ctrl->mbox_lock); | ||
367 | return tag; | ||
368 | } | ||
369 | |||
370 | wrb = wrb_from_mccq(phba); | ||
371 | req = embedded_payload(wrb); | ||
372 | wrb->tag0 |= tag; | ||
373 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
374 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
375 | OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, | ||
376 | sizeof(*req)); | ||
377 | |||
378 | be_mcc_notify(phba); | ||
379 | spin_unlock(&ctrl->mbox_lock); | ||
380 | return tag; | ||
381 | } | ||
382 | |||
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 00e816ee8070..3d316b82feb1 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -94,7 +94,8 @@ unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, | |||
94 | unsigned short cid, | 94 | unsigned short cid, |
95 | unsigned int upload_flag); | 95 | unsigned int upload_flag); |
96 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | 96 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, |
97 | unsigned int icd, unsigned int cid); | 97 | struct invalidate_command_table *inv_tbl, |
98 | unsigned int num_invalidate, unsigned int cid); | ||
98 | 99 | ||
99 | struct iscsi_invalidate_connection_params_in { | 100 | struct iscsi_invalidate_connection_params_in { |
100 | struct be_cmd_req_hdr hdr; | 101 | struct be_cmd_req_hdr hdr; |
@@ -116,11 +117,6 @@ union iscsi_invalidate_connection_params { | |||
116 | struct iscsi_invalidate_connection_params_out response; | 117 | struct iscsi_invalidate_connection_params_out response; |
117 | } __packed; | 118 | } __packed; |
118 | 119 | ||
119 | struct invalidate_command_table { | ||
120 | unsigned short icd; | ||
121 | unsigned short cid; | ||
122 | } __packed; | ||
123 | |||
124 | struct invalidate_commands_params_in { | 120 | struct invalidate_commands_params_in { |
125 | struct be_cmd_req_hdr hdr; | 121 | struct be_cmd_req_hdr hdr; |
126 | unsigned int ref_handle; | 122 | unsigned int ref_handle; |
@@ -175,7 +171,9 @@ struct mgmt_hba_attributes { | |||
175 | u8 phy_port; | 171 | u8 phy_port; |
176 | u32 firmware_post_status; | 172 | u32 firmware_post_status; |
177 | u32 hba_mtu[8]; | 173 | u32 hba_mtu[8]; |
178 | u32 future_u32[4]; | 174 | u8 iscsi_features; |
175 | u8 future_u8[3]; | ||
176 | u32 future_u32[3]; | ||
179 | } __packed; | 177 | } __packed; |
180 | 178 | ||
181 | struct mgmt_controller_attributes { | 179 | struct mgmt_controller_attributes { |
@@ -229,6 +227,7 @@ struct beiscsi_endpoint { | |||
229 | struct beiscsi_hba *phba; | 227 | struct beiscsi_hba *phba; |
230 | struct beiscsi_sess *sess; | 228 | struct beiscsi_sess *sess; |
231 | struct beiscsi_conn *conn; | 229 | struct beiscsi_conn *conn; |
230 | struct iscsi_endpoint *openiscsi_ep; | ||
232 | unsigned short ip_type; | 231 | unsigned short ip_type; |
233 | char dst6_addr[ISCSI_ADDRESS_BUF_LEN]; | 232 | char dst6_addr[ISCSI_ADDRESS_BUF_LEN]; |
234 | unsigned long dst_addr; | 233 | unsigned long dst_addr; |
@@ -246,4 +245,5 @@ unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | |||
246 | unsigned short cid, | 245 | unsigned short cid, |
247 | unsigned short issue_reset, | 246 | unsigned short issue_reset, |
248 | unsigned short savecfg_flag); | 247 | unsigned short savecfg_flag); |
248 | |||
249 | #endif | 249 | #endif |