blob: 56370587be91743545916b3f37fbcc63cd46e41d [file] [log] [blame]
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301/**
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -07002 * Copyright (C) 2005 - 2011 Emulex
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation. The full GNU General
8 * Public License is included in this distribution in the file called COPYING.
9 *
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070010 * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053011 *
12 * Contact Information:
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070013 * linux-drivers@emulex.com
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053014 *
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070015 * Emulex
16 * 3333 Susan Street
17 * Costa Mesa, CA 92626
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053018 */
Jayamohan Kallickal255fa9a2011-03-25 14:23:57 -070019
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053020#include <linux/reboot.h>
21#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053023#include <linux/interrupt.h>
24#include <linux/blkdev.h>
25#include <linux/pci.h>
26#include <linux/string.h>
27#include <linux/kernel.h>
28#include <linux/semaphore.h>
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +053029#include <linux/iscsi_boot_sysfs.h>
Paul Gortmakeracf3368f2011-05-27 09:47:43 -040030#include <linux/module.h>
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -050031#include <linux/bsg-lib.h>
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053032
33#include <scsi/libiscsi.h>
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -050034#include <scsi/scsi_bsg_iscsi.h>
35#include <scsi/scsi_netlink.h>
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053036#include <scsi/scsi_transport_iscsi.h>
37#include <scsi/scsi_transport.h>
38#include <scsi/scsi_cmnd.h>
39#include <scsi/scsi_device.h>
40#include <scsi/scsi_host.h>
41#include <scsi/scsi.h>
42#include "be_main.h"
43#include "be_iscsi.h"
44#include "be_mgmt.h"
45
46static unsigned int be_iopoll_budget = 10;
47static unsigned int be_max_phys_size = 64;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +053048static unsigned int enable_msix = 1;
Jayamohan Kallickale9b91192010-07-22 04:24:53 +053049static unsigned int gcrashmode = 0;
50static unsigned int num_hba = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053051
52MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
53MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
Jayamohan Kallickal76d15db2012-04-03 23:41:46 -050054MODULE_VERSION(BUILD_STR);
Jayamohan Kallickal2f635882012-04-03 23:41:45 -050055MODULE_AUTHOR("Emulex Corporation");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +053056MODULE_LICENSE("GPL");
57module_param(be_iopoll_budget, int, 0);
58module_param(enable_msix, int, 0);
59module_param(be_max_phys_size, uint, S_IRUGO);
John Soni Jose99bc5d52012-08-20 23:00:18 +053060MODULE_PARM_DESC(be_max_phys_size,
61 "Maximum Size (In Kilobytes) of physically contiguous "
62 "memory that can be allocated. Range is 16 - 128");
63
64#define beiscsi_disp_param(_name)\
65ssize_t \
66beiscsi_##_name##_disp(struct device *dev,\
67 struct device_attribute *attrib, char *buf) \
68{ \
69 struct Scsi_Host *shost = class_to_shost(dev);\
70 struct beiscsi_hba *phba = iscsi_host_priv(shost); \
71 uint32_t param_val = 0; \
72 param_val = phba->attr_##_name;\
73 return snprintf(buf, PAGE_SIZE, "%d\n",\
74 phba->attr_##_name);\
75}
76
77#define beiscsi_change_param(_name, _minval, _maxval, _defaval)\
78int \
79beiscsi_##_name##_change(struct beiscsi_hba *phba, uint32_t val)\
80{\
81 if (val >= _minval && val <= _maxval) {\
82 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\
83 "BA_%d : beiscsi_"#_name" updated "\
84 "from 0x%x ==> 0x%x\n",\
85 phba->attr_##_name, val); \
86 phba->attr_##_name = val;\
87 return 0;\
88 } \
89 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, \
90 "BA_%d beiscsi_"#_name" attribute "\
91 "cannot be updated to 0x%x, "\
92 "range allowed is ["#_minval" - "#_maxval"]\n", val);\
93 return -EINVAL;\
94}
95
96#define beiscsi_store_param(_name) \
97ssize_t \
98beiscsi_##_name##_store(struct device *dev,\
99 struct device_attribute *attr, const char *buf,\
100 size_t count) \
101{ \
102 struct Scsi_Host *shost = class_to_shost(dev);\
103 struct beiscsi_hba *phba = iscsi_host_priv(shost);\
104 uint32_t param_val = 0;\
105 if (!isdigit(buf[0]))\
106 return -EINVAL;\
107 if (sscanf(buf, "%i", &param_val) != 1)\
108 return -EINVAL;\
109 if (beiscsi_##_name##_change(phba, param_val) == 0) \
110 return strlen(buf);\
111 else \
112 return -EINVAL;\
113}
114
115#define beiscsi_init_param(_name, _minval, _maxval, _defval) \
116int \
117beiscsi_##_name##_init(struct beiscsi_hba *phba, uint32_t val) \
118{ \
119 if (val >= _minval && val <= _maxval) {\
120 phba->attr_##_name = val;\
121 return 0;\
122 } \
123 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\
124 "BA_%d beiscsi_"#_name" attribute " \
125 "cannot be updated to 0x%x, "\
126 "range allowed is ["#_minval" - "#_maxval"]\n", val);\
127 phba->attr_##_name = _defval;\
128 return -EINVAL;\
129}
130
131#define BEISCSI_RW_ATTR(_name, _minval, _maxval, _defval, _descp) \
132static uint beiscsi_##_name = _defval;\
133module_param(beiscsi_##_name, uint, S_IRUGO);\
134MODULE_PARM_DESC(beiscsi_##_name, _descp);\
135beiscsi_disp_param(_name)\
136beiscsi_change_param(_name, _minval, _maxval, _defval)\
137beiscsi_store_param(_name)\
138beiscsi_init_param(_name, _minval, _maxval, _defval)\
139DEVICE_ATTR(beiscsi_##_name, S_IRUGO | S_IWUSR,\
140 beiscsi_##_name##_disp, beiscsi_##_name##_store)
141
142/*
143 * When new log level added update the
144 * the MAX allowed value for log_enable
145 */
146BEISCSI_RW_ATTR(log_enable, 0x00,
147 0xFF, 0x00, "Enable logging Bit Mask\n"
148 "\t\t\t\tInitialization Events : 0x01\n"
149 "\t\t\t\tMailbox Events : 0x02\n"
150 "\t\t\t\tMiscellaneous Events : 0x04\n"
151 "\t\t\t\tError Handling : 0x08\n"
152 "\t\t\t\tIO Path Events : 0x10\n"
153 "\t\t\t\tConfiguration Path : 0x20\n");
154
155struct device_attribute *beiscsi_attrs[] = {
156 &dev_attr_beiscsi_log_enable,
157 NULL,
158};
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530159
160static int beiscsi_slave_configure(struct scsi_device *sdev)
161{
162 blk_queue_max_segment_size(sdev->request_queue, 65536);
163 return 0;
164}
165
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530166static int beiscsi_eh_abort(struct scsi_cmnd *sc)
167{
168 struct iscsi_cls_session *cls_session;
169 struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr;
170 struct beiscsi_io_task *aborted_io_task;
171 struct iscsi_conn *conn;
172 struct beiscsi_conn *beiscsi_conn;
173 struct beiscsi_hba *phba;
174 struct iscsi_session *session;
175 struct invalidate_command_table *inv_tbl;
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530176 struct be_dma_mem nonemb_cmd;
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530177 unsigned int cid, tag, num_invalidate;
178
179 cls_session = starget_to_session(scsi_target(sc->device));
180 session = cls_session->dd_data;
181
182 spin_lock_bh(&session->lock);
183 if (!aborted_task || !aborted_task->sc) {
184 /* we raced */
185 spin_unlock_bh(&session->lock);
186 return SUCCESS;
187 }
188
189 aborted_io_task = aborted_task->dd_data;
190 if (!aborted_io_task->scsi_cmnd) {
191 /* raced or invalid command */
192 spin_unlock_bh(&session->lock);
193 return SUCCESS;
194 }
195 spin_unlock_bh(&session->lock);
196 conn = aborted_task->conn;
197 beiscsi_conn = conn->dd_data;
198 phba = beiscsi_conn->phba;
199
200 /* invalidate iocb */
201 cid = beiscsi_conn->beiscsi_conn_cid;
202 inv_tbl = phba->inv_tbl;
203 memset(inv_tbl, 0x0, sizeof(*inv_tbl));
204 inv_tbl->cid = cid;
205 inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
206 num_invalidate = 1;
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530207 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
208 sizeof(struct invalidate_commands_params_in),
209 &nonemb_cmd.dma);
210 if (nonemb_cmd.va == NULL) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530211 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
212 "BM_%d : Failed to allocate memory for"
213 "mgmt_invalidate_icds\n");
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530214 return FAILED;
215 }
216 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
217
218 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
219 cid, &nonemb_cmd);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530220 if (!tag) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530221 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH,
222 "BM_%d : mgmt_invalidate_icds could not be"
223 "submitted\n");
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530224 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
225 nonemb_cmd.va, nonemb_cmd.dma);
226
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530227 return FAILED;
228 } else {
229 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
230 phba->ctrl.mcc_numtag[tag]);
231 free_mcc_tag(&phba->ctrl, tag);
232 }
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530233 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
234 nonemb_cmd.va, nonemb_cmd.dma);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530235 return iscsi_eh_abort(sc);
236}
237
238static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
239{
240 struct iscsi_task *abrt_task;
241 struct beiscsi_io_task *abrt_io_task;
242 struct iscsi_conn *conn;
243 struct beiscsi_conn *beiscsi_conn;
244 struct beiscsi_hba *phba;
245 struct iscsi_session *session;
246 struct iscsi_cls_session *cls_session;
247 struct invalidate_command_table *inv_tbl;
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530248 struct be_dma_mem nonemb_cmd;
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530249 unsigned int cid, tag, i, num_invalidate;
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530250
251 /* invalidate iocbs */
252 cls_session = starget_to_session(scsi_target(sc->device));
253 session = cls_session->dd_data;
254 spin_lock_bh(&session->lock);
Jayamohan Kallickaldb7f7702012-04-03 23:41:43 -0500255 if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) {
256 spin_unlock_bh(&session->lock);
257 return FAILED;
258 }
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530259 conn = session->leadconn;
260 beiscsi_conn = conn->dd_data;
261 phba = beiscsi_conn->phba;
262 cid = beiscsi_conn->beiscsi_conn_cid;
263 inv_tbl = phba->inv_tbl;
264 memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN);
265 num_invalidate = 0;
266 for (i = 0; i < conn->session->cmds_max; i++) {
267 abrt_task = conn->session->cmds[i];
268 abrt_io_task = abrt_task->dd_data;
269 if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
270 continue;
271
272 if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
273 continue;
274
275 inv_tbl->cid = cid;
276 inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index;
277 num_invalidate++;
278 inv_tbl++;
279 }
280 spin_unlock_bh(&session->lock);
281 inv_tbl = phba->inv_tbl;
282
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530283 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
284 sizeof(struct invalidate_commands_params_in),
285 &nonemb_cmd.dma);
286 if (nonemb_cmd.va == NULL) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530287 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
288 "BM_%d : Failed to allocate memory for"
289 "mgmt_invalidate_icds\n");
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530290 return FAILED;
291 }
292 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
293 memset(nonemb_cmd.va, 0, nonemb_cmd.size);
294 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
295 cid, &nonemb_cmd);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530296 if (!tag) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530297 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH,
298 "BM_%d : mgmt_invalidate_icds could not be"
299 " submitted\n");
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530300 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
301 nonemb_cmd.va, nonemb_cmd.dma);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530302 return FAILED;
303 } else {
304 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
305 phba->ctrl.mcc_numtag[tag]);
306 free_mcc_tag(&phba->ctrl, tag);
307 }
Jayamohan Kallickal3cbb7a72010-07-22 04:27:47 +0530308 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
309 nonemb_cmd.va, nonemb_cmd.dma);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530310 return iscsi_eh_device_reset(sc);
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530311}
312
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530313static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
314{
315 struct beiscsi_hba *phba = data;
Mike Christief457a462011-06-24 15:11:53 -0500316 struct mgmt_session_info *boot_sess = &phba->boot_sess;
317 struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530318 char *str = buf;
319 int rc;
320
321 switch (type) {
322 case ISCSI_BOOT_TGT_NAME:
323 rc = sprintf(buf, "%.*s\n",
Mike Christief457a462011-06-24 15:11:53 -0500324 (int)strlen(boot_sess->target_name),
325 (char *)&boot_sess->target_name);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530326 break;
327 case ISCSI_BOOT_TGT_IP_ADDR:
Mike Christief457a462011-06-24 15:11:53 -0500328 if (boot_conn->dest_ipaddr.ip_type == 0x1)
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530329 rc = sprintf(buf, "%pI4\n",
Mike Christie0e438952012-04-03 23:41:51 -0500330 (char *)&boot_conn->dest_ipaddr.addr);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530331 else
332 rc = sprintf(str, "%pI6\n",
Mike Christie0e438952012-04-03 23:41:51 -0500333 (char *)&boot_conn->dest_ipaddr.addr);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530334 break;
335 case ISCSI_BOOT_TGT_PORT:
Mike Christief457a462011-06-24 15:11:53 -0500336 rc = sprintf(str, "%d\n", boot_conn->dest_port);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530337 break;
338
339 case ISCSI_BOOT_TGT_CHAP_NAME:
340 rc = sprintf(str, "%.*s\n",
Mike Christief457a462011-06-24 15:11:53 -0500341 boot_conn->negotiated_login_options.auth_data.chap.
342 target_chap_name_length,
343 (char *)&boot_conn->negotiated_login_options.
344 auth_data.chap.target_chap_name);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530345 break;
346 case ISCSI_BOOT_TGT_CHAP_SECRET:
347 rc = sprintf(str, "%.*s\n",
Mike Christief457a462011-06-24 15:11:53 -0500348 boot_conn->negotiated_login_options.auth_data.chap.
349 target_secret_length,
350 (char *)&boot_conn->negotiated_login_options.
351 auth_data.chap.target_secret);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530352 break;
353 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
354 rc = sprintf(str, "%.*s\n",
Mike Christief457a462011-06-24 15:11:53 -0500355 boot_conn->negotiated_login_options.auth_data.chap.
356 intr_chap_name_length,
357 (char *)&boot_conn->negotiated_login_options.
358 auth_data.chap.intr_chap_name);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530359 break;
360 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
Mike Christief457a462011-06-24 15:11:53 -0500361 rc = sprintf(str, "%.*s\n",
362 boot_conn->negotiated_login_options.auth_data.chap.
363 intr_secret_length,
364 (char *)&boot_conn->negotiated_login_options.
365 auth_data.chap.intr_secret);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530366 break;
367 case ISCSI_BOOT_TGT_FLAGS:
Mike Christief457a462011-06-24 15:11:53 -0500368 rc = sprintf(str, "2\n");
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530369 break;
370 case ISCSI_BOOT_TGT_NIC_ASSOC:
Mike Christief457a462011-06-24 15:11:53 -0500371 rc = sprintf(str, "0\n");
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530372 break;
373 default:
374 rc = -ENOSYS;
375 break;
376 }
377 return rc;
378}
379
380static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf)
381{
382 struct beiscsi_hba *phba = data;
383 char *str = buf;
384 int rc;
385
386 switch (type) {
387 case ISCSI_BOOT_INI_INITIATOR_NAME:
388 rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname);
389 break;
390 default:
391 rc = -ENOSYS;
392 break;
393 }
394 return rc;
395}
396
397static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
398{
399 struct beiscsi_hba *phba = data;
400 char *str = buf;
401 int rc;
402
403 switch (type) {
404 case ISCSI_BOOT_ETH_FLAGS:
Mike Christief457a462011-06-24 15:11:53 -0500405 rc = sprintf(str, "2\n");
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530406 break;
407 case ISCSI_BOOT_ETH_INDEX:
Mike Christief457a462011-06-24 15:11:53 -0500408 rc = sprintf(str, "0\n");
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530409 break;
410 case ISCSI_BOOT_ETH_MAC:
Mike Christie0e438952012-04-03 23:41:51 -0500411 rc = beiscsi_get_macaddr(str, phba);
412 break;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530413 default:
414 rc = -ENOSYS;
415 break;
416 }
417 return rc;
418}
419
420
Al Viro587a1f12011-07-23 23:11:19 -0400421static umode_t beiscsi_tgt_get_attr_visibility(void *data, int type)
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530422{
Al Viro587a1f12011-07-23 23:11:19 -0400423 umode_t rc;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530424
425 switch (type) {
426 case ISCSI_BOOT_TGT_NAME:
427 case ISCSI_BOOT_TGT_IP_ADDR:
428 case ISCSI_BOOT_TGT_PORT:
429 case ISCSI_BOOT_TGT_CHAP_NAME:
430 case ISCSI_BOOT_TGT_CHAP_SECRET:
431 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
432 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
433 case ISCSI_BOOT_TGT_NIC_ASSOC:
434 case ISCSI_BOOT_TGT_FLAGS:
435 rc = S_IRUGO;
436 break;
437 default:
438 rc = 0;
439 break;
440 }
441 return rc;
442}
443
Al Viro587a1f12011-07-23 23:11:19 -0400444static umode_t beiscsi_ini_get_attr_visibility(void *data, int type)
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530445{
Al Viro587a1f12011-07-23 23:11:19 -0400446 umode_t rc;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530447
448 switch (type) {
449 case ISCSI_BOOT_INI_INITIATOR_NAME:
450 rc = S_IRUGO;
451 break;
452 default:
453 rc = 0;
454 break;
455 }
456 return rc;
457}
458
459
Al Viro587a1f12011-07-23 23:11:19 -0400460static umode_t beiscsi_eth_get_attr_visibility(void *data, int type)
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530461{
Al Viro587a1f12011-07-23 23:11:19 -0400462 umode_t rc;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530463
464 switch (type) {
465 case ISCSI_BOOT_ETH_FLAGS:
466 case ISCSI_BOOT_ETH_MAC:
467 case ISCSI_BOOT_ETH_INDEX:
468 rc = S_IRUGO;
469 break;
470 default:
471 rc = 0;
472 break;
473 }
474 return rc;
475}
476
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530477/*------------------- PCI Driver operations and data ----------------- */
478static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
479 { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
Jayamohan Kallickalf98c96b2010-02-11 05:11:15 +0530480 { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530481 { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
482 { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
483 { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530484 { 0 }
485};
486MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
487
John Soni Jose99bc5d52012-08-20 23:00:18 +0530488
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530489static struct scsi_host_template beiscsi_sht = {
490 .module = THIS_MODULE,
Jayamohan Kallickal2f635882012-04-03 23:41:45 -0500491 .name = "Emulex 10Gbe open-iscsi Initiator Driver",
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530492 .proc_name = DRV_NAME,
493 .queuecommand = iscsi_queuecommand,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530494 .change_queue_depth = iscsi_change_queue_depth,
495 .slave_configure = beiscsi_slave_configure,
496 .target_alloc = iscsi_target_alloc,
Jayamohan Kallickal41831222010-02-20 08:02:39 +0530497 .eh_abort_handler = beiscsi_eh_abort,
498 .eh_device_reset_handler = beiscsi_eh_device_reset,
Jayamohan Kallickal309ce152010-02-20 08:02:10 +0530499 .eh_target_reset_handler = iscsi_eh_session_reset,
John Soni Jose99bc5d52012-08-20 23:00:18 +0530500 .shost_attrs = beiscsi_attrs,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530501 .sg_tablesize = BEISCSI_SGLIST_ELEMENTS,
502 .can_queue = BE2_IO_DEPTH,
503 .this_id = -1,
504 .max_sectors = BEISCSI_MAX_SECTORS,
505 .cmd_per_lun = BEISCSI_CMD_PER_LUN,
506 .use_clustering = ENABLE_CLUSTERING,
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -0500507 .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
508
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530509};
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530510
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530511static struct scsi_transport_template *beiscsi_scsi_transport;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530512
513static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
514{
515 struct beiscsi_hba *phba;
516 struct Scsi_Host *shost;
517
518 shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0);
519 if (!shost) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530520 dev_err(&pcidev->dev,
521 "beiscsi_hba_alloc - iscsi_host_alloc failed\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530522 return NULL;
523 }
524 shost->dma_boundary = pcidev->dma_mask;
525 shost->max_id = BE2_MAX_SESSIONS;
526 shost->max_channel = 0;
527 shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
528 shost->max_lun = BEISCSI_NUM_MAX_LUN;
529 shost->transportt = beiscsi_scsi_transport;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530530 phba = iscsi_host_priv(shost);
531 memset(phba, 0, sizeof(*phba));
532 phba->shost = shost;
533 phba->pcidev = pci_dev_get(pcidev);
Jayamohan Kallickal2807afb2010-01-05 05:07:49 +0530534 pci_set_drvdata(pcidev, phba);
Mike Christie0e438952012-04-03 23:41:51 -0500535 phba->interface_handle = 0xFFFFFFFF;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530536
537 if (iscsi_host_add(shost, &phba->pcidev->dev))
538 goto free_devices;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +0530539
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530540 return phba;
541
542free_devices:
543 pci_dev_put(phba->pcidev);
544 iscsi_host_free(phba->shost);
545 return NULL;
546}
547
548static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba)
549{
550 if (phba->csr_va) {
551 iounmap(phba->csr_va);
552 phba->csr_va = NULL;
553 }
554 if (phba->db_va) {
555 iounmap(phba->db_va);
556 phba->db_va = NULL;
557 }
558 if (phba->pci_va) {
559 iounmap(phba->pci_va);
560 phba->pci_va = NULL;
561 }
562}
563
564static int beiscsi_map_pci_bars(struct beiscsi_hba *phba,
565 struct pci_dev *pcidev)
566{
567 u8 __iomem *addr;
Jayamohan Kallickalf98c96b2010-02-11 05:11:15 +0530568 int pcicfg_reg;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530569
570 addr = ioremap_nocache(pci_resource_start(pcidev, 2),
571 pci_resource_len(pcidev, 2));
572 if (addr == NULL)
573 return -ENOMEM;
574 phba->ctrl.csr = addr;
575 phba->csr_va = addr;
576 phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2);
577
578 addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024);
579 if (addr == NULL)
580 goto pci_map_err;
581 phba->ctrl.db = addr;
582 phba->db_va = addr;
583 phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4);
584
Jayamohan Kallickalf98c96b2010-02-11 05:11:15 +0530585 if (phba->generation == BE_GEN2)
586 pcicfg_reg = 1;
587 else
588 pcicfg_reg = 0;
589
590 addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg),
591 pci_resource_len(pcidev, pcicfg_reg));
592
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530593 if (addr == NULL)
594 goto pci_map_err;
595 phba->ctrl.pcicfg = addr;
596 phba->pci_va = addr;
Jayamohan Kallickalf98c96b2010-02-11 05:11:15 +0530597 phba->pci_pa.u.a64.address = pci_resource_start(pcidev, pcicfg_reg);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530598 return 0;
599
600pci_map_err:
601 beiscsi_unmap_pci_function(phba);
602 return -ENOMEM;
603}
604
605static int beiscsi_enable_pci(struct pci_dev *pcidev)
606{
607 int ret;
608
609 ret = pci_enable_device(pcidev);
610 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530611 dev_err(&pcidev->dev,
612 "beiscsi_enable_pci - enable device failed\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530613 return ret;
614 }
615
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530616 pci_set_master(pcidev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530617 if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
618 ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
619 if (ret) {
620 dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");
621 pci_disable_device(pcidev);
622 return ret;
623 }
624 }
625 return 0;
626}
627
628static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
629{
630 struct be_ctrl_info *ctrl = &phba->ctrl;
631 struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced;
632 struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem;
633 int status = 0;
634
635 ctrl->pdev = pdev;
636 status = beiscsi_map_pci_bars(phba, pdev);
637 if (status)
638 return status;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530639 mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
640 mbox_mem_alloc->va = pci_alloc_consistent(pdev,
641 mbox_mem_alloc->size,
642 &mbox_mem_alloc->dma);
643 if (!mbox_mem_alloc->va) {
644 beiscsi_unmap_pci_function(phba);
Jayamohan Kallickala49e06d2012-04-03 23:41:44 -0500645 return -ENOMEM;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530646 }
647
648 mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
649 mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
650 mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
651 memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
652 spin_lock_init(&ctrl->mbox_lock);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530653 spin_lock_init(&phba->ctrl.mcc_lock);
654 spin_lock_init(&phba->ctrl.mcc_cq_lock);
655
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530656 return status;
657}
658
659static void beiscsi_get_params(struct beiscsi_hba *phba)
660{
Jayamohan Kallickal7da50872010-01-05 05:04:12 +0530661 phba->params.ios_per_ctrl = (phba->fw_config.iscsi_icd_count
662 - (phba->fw_config.iscsi_cid_count
663 + BE2_TMFS
664 + BE2_NOPOUT_REQ));
665 phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count;
Jayamohan Kallickaled58ea22010-02-20 08:05:07 +0530666 phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2;
Justin P. Mattock6eab04a2011-04-08 19:49:08 -0700667 phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530668 phba->params.num_sge_per_io = BE2_SGE;
669 phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
670 phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
671 phba->params.eq_timer = 64;
672 phba->params.num_eq_entries =
Jayamohan Kallickal7da50872010-01-05 05:04:12 +0530673 (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2
674 + BE2_TMFS) / 512) + 1) * 512;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530675 phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024)
676 ? 1024 : phba->params.num_eq_entries;
John Soni Jose99bc5d52012-08-20 23:00:18 +0530677 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
678 "BM_%d : phba->params.num_eq_entries=%d\n",
679 phba->params.num_eq_entries);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530680 phba->params.num_cq_entries =
Jayamohan Kallickal7da50872010-01-05 05:04:12 +0530681 (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2
682 + BE2_TMFS) / 512) + 1) * 512;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530683 phba->params.wrbs_per_cxn = 256;
684}
685
686static void hwi_ring_eq_db(struct beiscsi_hba *phba,
687 unsigned int id, unsigned int clr_interrupt,
688 unsigned int num_processed,
689 unsigned char rearm, unsigned char event)
690{
691 u32 val = 0;
692 val |= id & DB_EQ_RING_ID_MASK;
693 if (rearm)
694 val |= 1 << DB_EQ_REARM_SHIFT;
695 if (clr_interrupt)
696 val |= 1 << DB_EQ_CLR_SHIFT;
697 if (event)
698 val |= 1 << DB_EQ_EVNT_SHIFT;
699 val |= num_processed << DB_EQ_NUM_POPPED_SHIFT;
700 iowrite32(val, phba->db_va + DB_EQ_OFFSET);
701}
702
703/**
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530704 * be_isr_mcc - The isr routine of the driver.
705 * @irq: Not used
706 * @dev_id: Pointer to host adapter structure
707 */
708static irqreturn_t be_isr_mcc(int irq, void *dev_id)
709{
710 struct beiscsi_hba *phba;
711 struct be_eq_entry *eqe = NULL;
712 struct be_queue_info *eq;
713 struct be_queue_info *mcc;
714 unsigned int num_eq_processed;
715 struct be_eq_obj *pbe_eq;
716 unsigned long flags;
717
718 pbe_eq = dev_id;
719 eq = &pbe_eq->q;
720 phba = pbe_eq->phba;
721 mcc = &phba->ctrl.mcc_obj.cq;
722 eqe = queue_tail_node(eq);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530723
724 num_eq_processed = 0;
725
726 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
727 & EQE_VALID_MASK) {
728 if (((eqe->dw[offsetof(struct amap_eq_entry,
729 resource_id) / 32] &
730 EQE_RESID_MASK) >> 16) == mcc->id) {
731 spin_lock_irqsave(&phba->isr_lock, flags);
732 phba->todo_mcc_cq = 1;
733 spin_unlock_irqrestore(&phba->isr_lock, flags);
734 }
735 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
736 queue_tail_inc(eq);
737 eqe = queue_tail_node(eq);
738 num_eq_processed++;
739 }
740 if (phba->todo_mcc_cq)
741 queue_work(phba->wq, &phba->work_cqs);
742 if (num_eq_processed)
743 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
744
745 return IRQ_HANDLED;
746}
747
748/**
749 * be_isr_msix - The isr routine of the driver.
750 * @irq: Not used
751 * @dev_id: Pointer to host adapter structure
752 */
753static irqreturn_t be_isr_msix(int irq, void *dev_id)
754{
755 struct beiscsi_hba *phba;
756 struct be_eq_entry *eqe = NULL;
757 struct be_queue_info *eq;
758 struct be_queue_info *cq;
759 unsigned int num_eq_processed;
760 struct be_eq_obj *pbe_eq;
761 unsigned long flags;
762
763 pbe_eq = dev_id;
764 eq = &pbe_eq->q;
765 cq = pbe_eq->cq;
766 eqe = queue_tail_node(eq);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530767
768 phba = pbe_eq->phba;
769 num_eq_processed = 0;
770 if (blk_iopoll_enabled) {
771 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
772 & EQE_VALID_MASK) {
773 if (!blk_iopoll_sched_prep(&pbe_eq->iopoll))
774 blk_iopoll_sched(&pbe_eq->iopoll);
775
776 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
777 queue_tail_inc(eq);
778 eqe = queue_tail_node(eq);
779 num_eq_processed++;
780 }
781 if (num_eq_processed)
782 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
783
784 return IRQ_HANDLED;
785 } else {
786 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
787 & EQE_VALID_MASK) {
788 spin_lock_irqsave(&phba->isr_lock, flags);
789 phba->todo_cq = 1;
790 spin_unlock_irqrestore(&phba->isr_lock, flags);
791 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
792 queue_tail_inc(eq);
793 eqe = queue_tail_node(eq);
794 num_eq_processed++;
795 }
796 if (phba->todo_cq)
797 queue_work(phba->wq, &phba->work_cqs);
798
799 if (num_eq_processed)
800 hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1);
801
802 return IRQ_HANDLED;
803 }
804}
805
806/**
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530807 * be_isr - The isr routine of the driver.
808 * @irq: Not used
809 * @dev_id: Pointer to host adapter structure
810 */
811static irqreturn_t be_isr(int irq, void *dev_id)
812{
813 struct beiscsi_hba *phba;
814 struct hwi_controller *phwi_ctrlr;
815 struct hwi_context_memory *phwi_context;
816 struct be_eq_entry *eqe = NULL;
817 struct be_queue_info *eq;
818 struct be_queue_info *cq;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530819 struct be_queue_info *mcc;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530820 unsigned long flags, index;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530821 unsigned int num_mcceq_processed, num_ioeq_processed;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530822 struct be_ctrl_info *ctrl;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530823 struct be_eq_obj *pbe_eq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530824 int isr;
825
826 phba = dev_id;
Justin P. Mattock6eab04a2011-04-08 19:49:08 -0700827 ctrl = &phba->ctrl;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530828 isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
829 (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));
830 if (!isr)
831 return IRQ_NONE;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530832
833 phwi_ctrlr = phba->phwi_ctrlr;
834 phwi_context = phwi_ctrlr->phwi_ctxt;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530835 pbe_eq = &phwi_context->be_eq[0];
836
837 eq = &phwi_context->be_eq[0].q;
838 mcc = &phba->ctrl.mcc_obj.cq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530839 index = 0;
840 eqe = queue_tail_node(eq);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530841
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530842 num_ioeq_processed = 0;
843 num_mcceq_processed = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530844 if (blk_iopoll_enabled) {
845 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
846 & EQE_VALID_MASK) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530847 if (((eqe->dw[offsetof(struct amap_eq_entry,
848 resource_id) / 32] &
849 EQE_RESID_MASK) >> 16) == mcc->id) {
850 spin_lock_irqsave(&phba->isr_lock, flags);
851 phba->todo_mcc_cq = 1;
852 spin_unlock_irqrestore(&phba->isr_lock, flags);
853 num_mcceq_processed++;
854 } else {
855 if (!blk_iopoll_sched_prep(&pbe_eq->iopoll))
856 blk_iopoll_sched(&pbe_eq->iopoll);
857 num_ioeq_processed++;
858 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530859 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
860 queue_tail_inc(eq);
861 eqe = queue_tail_node(eq);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530862 }
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530863 if (num_ioeq_processed || num_mcceq_processed) {
864 if (phba->todo_mcc_cq)
865 queue_work(phba->wq, &phba->work_cqs);
866
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +0530867 if ((num_mcceq_processed) && (!num_ioeq_processed))
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530868 hwi_ring_eq_db(phba, eq->id, 0,
869 (num_ioeq_processed +
870 num_mcceq_processed) , 1, 1);
871 else
872 hwi_ring_eq_db(phba, eq->id, 0,
873 (num_ioeq_processed +
874 num_mcceq_processed), 0, 1);
875
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530876 return IRQ_HANDLED;
877 } else
878 return IRQ_NONE;
879 } else {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530880 cq = &phwi_context->be_cq[0];
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530881 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
882 & EQE_VALID_MASK) {
883
884 if (((eqe->dw[offsetof(struct amap_eq_entry,
885 resource_id) / 32] &
886 EQE_RESID_MASK) >> 16) != cq->id) {
887 spin_lock_irqsave(&phba->isr_lock, flags);
888 phba->todo_mcc_cq = 1;
889 spin_unlock_irqrestore(&phba->isr_lock, flags);
890 } else {
891 spin_lock_irqsave(&phba->isr_lock, flags);
892 phba->todo_cq = 1;
893 spin_unlock_irqrestore(&phba->isr_lock, flags);
894 }
895 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
896 queue_tail_inc(eq);
897 eqe = queue_tail_node(eq);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530898 num_ioeq_processed++;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530899 }
900 if (phba->todo_cq || phba->todo_mcc_cq)
901 queue_work(phba->wq, &phba->work_cqs);
902
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530903 if (num_ioeq_processed) {
904 hwi_ring_eq_db(phba, eq->id, 0,
905 num_ioeq_processed, 1, 1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530906 return IRQ_HANDLED;
907 } else
908 return IRQ_NONE;
909 }
910}
911
912static int beiscsi_init_irqs(struct beiscsi_hba *phba)
913{
914 struct pci_dev *pcidev = phba->pcidev;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530915 struct hwi_controller *phwi_ctrlr;
916 struct hwi_context_memory *phwi_context;
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530917 int ret, msix_vec, i, j;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530918
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530919 phwi_ctrlr = phba->phwi_ctrlr;
920 phwi_context = phwi_ctrlr->phwi_ctxt;
921
922 if (phba->msix_enabled) {
923 for (i = 0; i < phba->num_cpus; i++) {
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700924 phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME,
925 GFP_KERNEL);
926 if (!phba->msi_name[i]) {
927 ret = -ENOMEM;
928 goto free_msix_irqs;
929 }
930
931 sprintf(phba->msi_name[i], "beiscsi_%02x_%02x",
932 phba->shost->host_no, i);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530933 msix_vec = phba->msix_entries[i].vector;
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700934 ret = request_irq(msix_vec, be_isr_msix, 0,
935 phba->msi_name[i],
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530936 &phwi_context->be_eq[i]);
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530937 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530938 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
939 "BM_%d : beiscsi_init_irqs-Failed to"
940 "register msix for i = %d\n",
941 i);
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700942 kfree(phba->msi_name[i]);
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530943 goto free_msix_irqs;
944 }
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530945 }
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700946 phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL);
947 if (!phba->msi_name[i]) {
948 ret = -ENOMEM;
949 goto free_msix_irqs;
950 }
951 sprintf(phba->msi_name[i], "beiscsi_mcc_%02x",
952 phba->shost->host_no);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530953 msix_vec = phba->msix_entries[i].vector;
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700954 ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530955 &phwi_context->be_eq[i]);
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530956 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530957 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT ,
958 "BM_%d : beiscsi_init_irqs-"
959 "Failed to register beiscsi_msix_mcc\n");
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700960 kfree(phba->msi_name[i]);
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530961 goto free_msix_irqs;
962 }
963
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530964 } else {
965 ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED,
966 "beiscsi", phba);
967 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +0530968 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
969 "BM_%d : beiscsi_init_irqs-"
970 "Failed to register irq\\n");
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +0530971 return ret;
972 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530973 }
974 return 0;
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530975free_msix_irqs:
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700976 for (j = i - 1; j >= 0; j--) {
977 kfree(phba->msi_name[j]);
978 msix_vec = phba->msix_entries[j].vector;
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530979 free_irq(msix_vec, &phwi_context->be_eq[j]);
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -0700980 }
Jayamohan Kallickal4f5af072010-07-22 04:23:55 +0530981 return ret;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530982}
983
984static void hwi_ring_cq_db(struct beiscsi_hba *phba,
985 unsigned int id, unsigned int num_processed,
986 unsigned char rearm, unsigned char event)
987{
988 u32 val = 0;
989 val |= id & DB_CQ_RING_ID_MASK;
990 if (rearm)
991 val |= 1 << DB_CQ_REARM_SHIFT;
992 val |= num_processed << DB_CQ_NUM_POPPED_SHIFT;
993 iowrite32(val, phba->db_va + DB_CQ_OFFSET);
994}
995
Jayamohan Kallickal6733b392009-09-05 07:36:35 +0530996static unsigned int
997beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,
998 struct beiscsi_hba *phba,
999 unsigned short cid,
1000 struct pdu_base *ppdu,
1001 unsigned long pdu_len,
1002 void *pbuffer, unsigned long buf_len)
1003{
1004 struct iscsi_conn *conn = beiscsi_conn->conn;
1005 struct iscsi_session *session = conn->session;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301006 struct iscsi_task *task;
1007 struct beiscsi_io_task *io_task;
1008 struct iscsi_hdr *login_hdr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301009
1010 switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] &
1011 PDUBASE_OPCODE_MASK) {
1012 case ISCSI_OP_NOOP_IN:
1013 pbuffer = NULL;
1014 buf_len = 0;
1015 break;
1016 case ISCSI_OP_ASYNC_EVENT:
1017 break;
1018 case ISCSI_OP_REJECT:
1019 WARN_ON(!pbuffer);
1020 WARN_ON(!(buf_len == 48));
John Soni Jose99bc5d52012-08-20 23:00:18 +05301021 beiscsi_log(phba, KERN_ERR,
1022 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1023 "BM_%d : In ISCSI_OP_REJECT\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301024 break;
1025 case ISCSI_OP_LOGIN_RSP:
Jayamohan Kallickal7bd6e252010-01-05 05:07:02 +05301026 case ISCSI_OP_TEXT_RSP:
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301027 task = conn->login_task;
1028 io_task = task->dd_data;
1029 login_hdr = (struct iscsi_hdr *)ppdu;
1030 login_hdr->itt = io_task->libiscsi_itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301031 break;
1032 default:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301033 beiscsi_log(phba, KERN_WARNING,
1034 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1035 "BM_%d : Unrecognized opcode 0x%x in async msg\n",
1036 (ppdu->
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301037 dw[offsetof(struct amap_pdu_base, opcode) / 32]
John Soni Jose99bc5d52012-08-20 23:00:18 +05301038 & PDUBASE_OPCODE_MASK));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301039 return 1;
1040 }
1041
1042 spin_lock_bh(&session->lock);
1043 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len);
1044 spin_unlock_bh(&session->lock);
1045 return 0;
1046}
1047
1048static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
1049{
1050 struct sgl_handle *psgl_handle;
1051
1052 if (phba->io_sgl_hndl_avbl) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05301053 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
1054 "BM_%d : In alloc_io_sgl_handle,"
1055 " io_sgl_alloc_index=%d\n",
1056 phba->io_sgl_alloc_index);
1057
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301058 psgl_handle = phba->io_sgl_hndl_base[phba->
1059 io_sgl_alloc_index];
1060 phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL;
1061 phba->io_sgl_hndl_avbl--;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301062 if (phba->io_sgl_alloc_index == (phba->params.
1063 ios_per_ctrl - 1))
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301064 phba->io_sgl_alloc_index = 0;
1065 else
1066 phba->io_sgl_alloc_index++;
1067 } else
1068 psgl_handle = NULL;
1069 return psgl_handle;
1070}
1071
1072static void
1073free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
1074{
John Soni Jose99bc5d52012-08-20 23:00:18 +05301075 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
1076 "BM_%d : In free_,io_sgl_free_index=%d\n",
1077 phba->io_sgl_free_index);
1078
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301079 if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) {
1080 /*
1081 * this can happen if clean_task is called on a task that
1082 * failed in xmit_task or alloc_pdu.
1083 */
John Soni Jose99bc5d52012-08-20 23:00:18 +05301084 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
1085 "BM_%d : Double Free in IO SGL io_sgl_free_index=%d,"
1086 "value there=%p\n", phba->io_sgl_free_index,
1087 phba->io_sgl_hndl_base
1088 [phba->io_sgl_free_index]);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301089 return;
1090 }
1091 phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
1092 phba->io_sgl_hndl_avbl++;
1093 if (phba->io_sgl_free_index == (phba->params.ios_per_ctrl - 1))
1094 phba->io_sgl_free_index = 0;
1095 else
1096 phba->io_sgl_free_index++;
1097}
1098
1099/**
1100 * alloc_wrb_handle - To allocate a wrb handle
1101 * @phba: The hba pointer
1102 * @cid: The cid to use for allocation
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301103 *
1104 * This happens under session_lock until submission to chip
1105 */
Jayamohan Kallickald5431482010-01-05 05:06:21 +05301106struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301107{
1108 struct hwi_wrb_context *pwrb_context;
1109 struct hwi_controller *phwi_ctrlr;
Jayamohan Kallickald5431482010-01-05 05:06:21 +05301110 struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301111
1112 phwi_ctrlr = phba->phwi_ctrlr;
1113 pwrb_context = &phwi_ctrlr->wrb_context[cid];
Jayamohan Kallickald5431482010-01-05 05:06:21 +05301114 if (pwrb_context->wrb_handles_available >= 2) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301115 pwrb_handle = pwrb_context->pwrb_handle_base[
1116 pwrb_context->alloc_index];
1117 pwrb_context->wrb_handles_available--;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301118 if (pwrb_context->alloc_index ==
1119 (phba->params.wrbs_per_cxn - 1))
1120 pwrb_context->alloc_index = 0;
1121 else
1122 pwrb_context->alloc_index++;
Jayamohan Kallickald5431482010-01-05 05:06:21 +05301123 pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
1124 pwrb_context->alloc_index];
1125 pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301126 } else
1127 pwrb_handle = NULL;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301128 return pwrb_handle;
1129}
1130
1131/**
1132 * free_wrb_handle - To free the wrb handle back to pool
1133 * @phba: The hba pointer
1134 * @pwrb_context: The context to free from
1135 * @pwrb_handle: The wrb_handle to free
1136 *
1137 * This happens under session_lock until submission to chip
1138 */
1139static void
1140free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
1141 struct wrb_handle *pwrb_handle)
1142{
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301143 pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301144 pwrb_context->wrb_handles_available++;
1145 if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1))
1146 pwrb_context->free_index = 0;
1147 else
1148 pwrb_context->free_index++;
1149
John Soni Jose99bc5d52012-08-20 23:00:18 +05301150 beiscsi_log(phba, KERN_INFO,
1151 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1152 "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x"
1153 "wrb_handles_available=%d\n",
1154 pwrb_handle, pwrb_context->free_index,
1155 pwrb_context->wrb_handles_available);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301156}
1157
1158static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
1159{
1160 struct sgl_handle *psgl_handle;
1161
1162 if (phba->eh_sgl_hndl_avbl) {
1163 psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
1164 phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
John Soni Jose99bc5d52012-08-20 23:00:18 +05301165 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1166 "BM_%d : mgmt_sgl_alloc_index=%d=0x%x\n",
1167 phba->eh_sgl_alloc_index,
1168 phba->eh_sgl_alloc_index);
1169
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301170 phba->eh_sgl_hndl_avbl--;
1171 if (phba->eh_sgl_alloc_index ==
1172 (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl -
1173 1))
1174 phba->eh_sgl_alloc_index = 0;
1175 else
1176 phba->eh_sgl_alloc_index++;
1177 } else
1178 psgl_handle = NULL;
1179 return psgl_handle;
1180}
1181
1182void
1183free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
1184{
1185
John Soni Jose99bc5d52012-08-20 23:00:18 +05301186 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1187 "BM_%d : In free_mgmt_sgl_handle,"
1188 "eh_sgl_free_index=%d\n",
1189 phba->eh_sgl_free_index);
1190
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301191 if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) {
1192 /*
1193 * this can happen if clean_task is called on a task that
1194 * failed in xmit_task or alloc_pdu.
1195 */
John Soni Jose99bc5d52012-08-20 23:00:18 +05301196 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
1197 "BM_%d : Double Free in eh SGL ,"
1198 "eh_sgl_free_index=%d\n",
1199 phba->eh_sgl_free_index);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301200 return;
1201 }
1202 phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle;
1203 phba->eh_sgl_hndl_avbl++;
1204 if (phba->eh_sgl_free_index ==
1205 (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 1))
1206 phba->eh_sgl_free_index = 0;
1207 else
1208 phba->eh_sgl_free_index++;
1209}
1210
1211static void
1212be_complete_io(struct beiscsi_conn *beiscsi_conn,
1213 struct iscsi_task *task, struct sol_cqe *psol)
1214{
1215 struct beiscsi_io_task *io_task = task->dd_data;
1216 struct be_status_bhs *sts_bhs =
1217 (struct be_status_bhs *)io_task->cmd_bhs;
1218 struct iscsi_conn *conn = beiscsi_conn->conn;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301219 unsigned char *sense;
1220 u32 resid = 0, exp_cmdsn, max_cmdsn;
1221 u8 rsp, status, flags;
1222
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301223 exp_cmdsn = (psol->
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301224 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
1225 & SOL_EXP_CMD_SN_MASK);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301226 max_cmdsn = ((psol->
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301227 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
1228 & SOL_EXP_CMD_SN_MASK) +
1229 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
1230 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
1231 rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32]
1232 & SOL_RESP_MASK) >> 16);
1233 status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32]
1234 & SOL_STS_MASK) >> 8);
1235 flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
1236 & SOL_FLAGS_MASK) >> 24) | 0x80;
Jayamohan Kallickalbd535452011-10-07 19:31:10 -05001237 if (!task->sc) {
1238 if (io_task->scsi_cmnd)
1239 scsi_dma_unmap(io_task->scsi_cmnd);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301240
Jayamohan Kallickalbd535452011-10-07 19:31:10 -05001241 return;
1242 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301243 task->sc->result = (DID_OK << 16) | status;
1244 if (rsp != ISCSI_STATUS_CMD_COMPLETED) {
1245 task->sc->result = DID_ERROR << 16;
1246 goto unmap;
1247 }
1248
1249 /* bidi not initially supported */
1250 if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) {
1251 resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) /
1252 32] & SOL_RES_CNT_MASK);
1253
1254 if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))
1255 task->sc->result = DID_ERROR << 16;
1256
1257 if (flags & ISCSI_FLAG_CMD_UNDERFLOW) {
1258 scsi_set_resid(task->sc, resid);
1259 if (!status && (scsi_bufflen(task->sc) - resid <
1260 task->sc->underflow))
1261 task->sc->result = DID_ERROR << 16;
1262 }
1263 }
1264
1265 if (status == SAM_STAT_CHECK_CONDITION) {
Dan Carpenter4053a4b2011-09-26 09:23:37 +03001266 u16 sense_len;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301267 unsigned short *slen = (unsigned short *)sts_bhs->sense_info;
Dan Carpenter4053a4b2011-09-26 09:23:37 +03001268
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301269 sense = sts_bhs->sense_info + sizeof(unsigned short);
Dan Carpenter4053a4b2011-09-26 09:23:37 +03001270 sense_len = be16_to_cpu(*slen);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301271 memcpy(task->sc->sense_buffer, sense,
1272 min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));
1273 }
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05301274
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301275 if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) {
1276 if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
1277 & SOL_RES_CNT_MASK)
1278 conn->rxdata_octets += (psol->
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301279 dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32]
1280 & SOL_RES_CNT_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301281 }
1282unmap:
1283 scsi_dma_unmap(io_task->scsi_cmnd);
1284 iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);
1285}
1286
1287static void
1288be_complete_logout(struct beiscsi_conn *beiscsi_conn,
1289 struct iscsi_task *task, struct sol_cqe *psol)
1290{
1291 struct iscsi_logout_rsp *hdr;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301292 struct beiscsi_io_task *io_task = task->dd_data;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301293 struct iscsi_conn *conn = beiscsi_conn->conn;
1294
1295 hdr = (struct iscsi_logout_rsp *)task->hdr;
Jayamohan Kallickal7bd6e252010-01-05 05:07:02 +05301296 hdr->opcode = ISCSI_OP_LOGOUT_RSP;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301297 hdr->t2wait = 5;
1298 hdr->t2retain = 0;
1299 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
1300 & SOL_FLAGS_MASK) >> 24) | 0x80;
1301 hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
1302 32] & SOL_RESP_MASK);
1303 hdr->exp_cmdsn = cpu_to_be32(psol->
1304 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
1305 & SOL_EXP_CMD_SN_MASK);
1306 hdr->max_cmdsn = be32_to_cpu((psol->
1307 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32]
1308 & SOL_EXP_CMD_SN_MASK) +
1309 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
1310 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
Jayamohan Kallickal7bd6e252010-01-05 05:07:02 +05301311 hdr->dlength[0] = 0;
1312 hdr->dlength[1] = 0;
1313 hdr->dlength[2] = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301314 hdr->hlength = 0;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301315 hdr->itt = io_task->libiscsi_itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301316 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
1317}
1318
1319static void
1320be_complete_tmf(struct beiscsi_conn *beiscsi_conn,
1321 struct iscsi_task *task, struct sol_cqe *psol)
1322{
1323 struct iscsi_tm_rsp *hdr;
1324 struct iscsi_conn *conn = beiscsi_conn->conn;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301325 struct beiscsi_io_task *io_task = task->dd_data;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301326
1327 hdr = (struct iscsi_tm_rsp *)task->hdr;
Jayamohan Kallickal7bd6e252010-01-05 05:07:02 +05301328 hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301329 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
1330 & SOL_FLAGS_MASK) >> 24) | 0x80;
1331 hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) /
1332 32] & SOL_RESP_MASK);
1333 hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301334 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301335 hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
1336 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
1337 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
1338 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301339 hdr->itt = io_task->libiscsi_itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301340 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
1341}
1342
1343static void
1344hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
1345 struct beiscsi_hba *phba, struct sol_cqe *psol)
1346{
1347 struct hwi_wrb_context *pwrb_context;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301348 struct wrb_handle *pwrb_handle = NULL;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301349 struct hwi_controller *phwi_ctrlr;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301350 struct iscsi_task *task;
1351 struct beiscsi_io_task *io_task;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301352 struct iscsi_conn *conn = beiscsi_conn->conn;
1353 struct iscsi_session *session = conn->session;
1354
1355 phwi_ctrlr = phba->phwi_ctrlr;
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301356 pwrb_context = &phwi_ctrlr->wrb_context[((psol->
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301357 dw[offsetof(struct amap_sol_cqe, cid) / 32] &
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05301358 SOL_CID_MASK) >> 6) -
1359 phba->fw_config.iscsi_cid_start];
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301360 pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301361 dw[offsetof(struct amap_sol_cqe, wrb_index) /
1362 32] & SOL_WRB_INDEX_MASK) >> 16)];
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301363 task = pwrb_handle->pio_handle;
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301364
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301365 io_task = task->dd_data;
Mike Christie1282ab72012-04-18 03:06:00 -05001366 spin_lock_bh(&phba->mgmt_sgl_lock);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301367 free_mgmt_sgl_handle(phba, io_task->psgl_handle);
Mike Christie1282ab72012-04-18 03:06:00 -05001368 spin_unlock_bh(&phba->mgmt_sgl_lock);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301369 spin_lock_bh(&session->lock);
1370 free_wrb_handle(phba, pwrb_context, pwrb_handle);
1371 spin_unlock_bh(&session->lock);
1372}
1373
1374static void
1375be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn,
1376 struct iscsi_task *task, struct sol_cqe *psol)
1377{
1378 struct iscsi_nopin *hdr;
1379 struct iscsi_conn *conn = beiscsi_conn->conn;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301380 struct beiscsi_io_task *io_task = task->dd_data;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301381
1382 hdr = (struct iscsi_nopin *)task->hdr;
1383 hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32]
1384 & SOL_FLAGS_MASK) >> 24) | 0x80;
1385 hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe,
1386 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK);
1387 hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe,
1388 i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) +
1389 ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd)
1390 / 32] & SOL_CMD_WND_MASK) >> 24) - 1);
1391 hdr->opcode = ISCSI_OP_NOOP_IN;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301392 hdr->itt = io_task->libiscsi_itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301393 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
1394}
1395
1396static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
1397 struct beiscsi_hba *phba, struct sol_cqe *psol)
1398{
1399 struct hwi_wrb_context *pwrb_context;
1400 struct wrb_handle *pwrb_handle;
1401 struct iscsi_wrb *pwrb = NULL;
1402 struct hwi_controller *phwi_ctrlr;
1403 struct iscsi_task *task;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301404 unsigned int type;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301405 struct iscsi_conn *conn = beiscsi_conn->conn;
1406 struct iscsi_session *session = conn->session;
1407
1408 phwi_ctrlr = phba->phwi_ctrlr;
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301409 pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301410 (struct amap_sol_cqe, cid) / 32]
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05301411 & SOL_CID_MASK) >> 6) -
1412 phba->fw_config.iscsi_cid_start];
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301413 pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol->
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301414 dw[offsetof(struct amap_sol_cqe, wrb_index) /
1415 32] & SOL_WRB_INDEX_MASK) >> 16)];
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301416 task = pwrb_handle->pio_handle;
1417 pwrb = pwrb_handle->pwrb;
1418 type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] &
1419 WRB_TYPE_MASK) >> 28;
1420
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301421 spin_lock_bh(&session->lock);
1422 switch (type) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301423 case HWH_TYPE_IO:
1424 case HWH_TYPE_IO_RD:
1425 if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05301426 ISCSI_OP_NOOP_OUT)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301427 be_complete_nopin_resp(beiscsi_conn, task, psol);
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05301428 else
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301429 be_complete_io(beiscsi_conn, task, psol);
1430 break;
1431
1432 case HWH_TYPE_LOGOUT:
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05301433 if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
1434 be_complete_logout(beiscsi_conn, task, psol);
1435 else
1436 be_complete_tmf(beiscsi_conn, task, psol);
1437
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301438 break;
1439
1440 case HWH_TYPE_LOGIN:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301441 beiscsi_log(phba, KERN_ERR,
1442 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1443 "BM_%d :\t\t No HWH_TYPE_LOGIN Expected in"
1444 " hwi_complete_cmd- Solicited path\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301445 break;
1446
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301447 case HWH_TYPE_NOP:
1448 be_complete_nopin_resp(beiscsi_conn, task, psol);
1449 break;
1450
1451 default:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301452 beiscsi_log(phba, KERN_WARNING,
1453 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1454 "BM_%d : In hwi_complete_cmd, unknown type = %d"
1455 "wrb_index 0x%x CID 0x%x\n", type,
1456 ((psol->dw[offsetof(struct amap_iscsi_wrb,
1457 type) / 32] & SOL_WRB_INDEX_MASK) >> 16),
1458 ((psol->dw[offsetof(struct amap_sol_cqe,
1459 cid) / 32] & SOL_CID_MASK) >> 6));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301460 break;
1461 }
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05301462
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301463 spin_unlock_bh(&session->lock);
1464}
1465
1466static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context
1467 *pasync_ctx, unsigned int is_header,
1468 unsigned int host_write_ptr)
1469{
1470 if (is_header)
1471 return &pasync_ctx->async_entry[host_write_ptr].
1472 header_busy_list;
1473 else
1474 return &pasync_ctx->async_entry[host_write_ptr].data_busy_list;
1475}
1476
1477static struct async_pdu_handle *
1478hwi_get_async_handle(struct beiscsi_hba *phba,
1479 struct beiscsi_conn *beiscsi_conn,
1480 struct hwi_async_pdu_context *pasync_ctx,
1481 struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index)
1482{
1483 struct be_bus_address phys_addr;
1484 struct list_head *pbusy_list;
1485 struct async_pdu_handle *pasync_handle = NULL;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301486 unsigned char is_header = 0;
1487
1488 phys_addr.u.a32.address_lo =
1489 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] -
1490 ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
1491 & PDUCQE_DPL_MASK) >> 16);
1492 phys_addr.u.a32.address_hi =
1493 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32];
1494
1495 phys_addr.u.a64.address =
1496 *((unsigned long long *)(&phys_addr.u.a64.address));
1497
1498 switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32]
1499 & PDUCQE_CODE_MASK) {
1500 case UNSOL_HDR_NOTIFY:
1501 is_header = 1;
1502
1503 pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1,
1504 (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
1505 index) / 32] & PDUCQE_INDEX_MASK));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301506 break;
1507 case UNSOL_DATA_NOTIFY:
1508 pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe->
1509 dw[offsetof(struct amap_i_t_dpdu_cqe,
1510 index) / 32] & PDUCQE_INDEX_MASK));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301511 break;
1512 default:
1513 pbusy_list = NULL;
John Soni Jose99bc5d52012-08-20 23:00:18 +05301514 beiscsi_log(phba, KERN_WARNING,
1515 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1516 "BM_%d : Unexpected code=%d\n",
1517 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
1518 code) / 32] & PDUCQE_CODE_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301519 return NULL;
1520 }
1521
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301522 WARN_ON(list_empty(pbusy_list));
1523 list_for_each_entry(pasync_handle, pbusy_list, link) {
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05001524 if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301525 break;
1526 }
1527
1528 WARN_ON(!pasync_handle);
1529
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05301530 pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid -
1531 phba->fw_config.iscsi_cid_start;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301532 pasync_handle->is_header = is_header;
1533 pasync_handle->buffer_len = ((pdpdu_cqe->
1534 dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32]
1535 & PDUCQE_DPL_MASK) >> 16);
1536
1537 *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe,
1538 index) / 32] & PDUCQE_INDEX_MASK);
1539 return pasync_handle;
1540}
1541
1542static unsigned int
John Soni Jose99bc5d52012-08-20 23:00:18 +05301543hwi_update_async_writables(struct beiscsi_hba *phba,
1544 struct hwi_async_pdu_context *pasync_ctx,
1545 unsigned int is_header, unsigned int cq_index)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301546{
1547 struct list_head *pbusy_list;
1548 struct async_pdu_handle *pasync_handle;
1549 unsigned int num_entries, writables = 0;
1550 unsigned int *pep_read_ptr, *pwritables;
1551
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05001552 num_entries = pasync_ctx->num_entries;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301553 if (is_header) {
1554 pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr;
1555 pwritables = &pasync_ctx->async_header.writables;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301556 } else {
1557 pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr;
1558 pwritables = &pasync_ctx->async_data.writables;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301559 }
1560
1561 while ((*pep_read_ptr) != cq_index) {
1562 (*pep_read_ptr)++;
1563 *pep_read_ptr = (*pep_read_ptr) % num_entries;
1564
1565 pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header,
1566 *pep_read_ptr);
1567 if (writables == 0)
1568 WARN_ON(list_empty(pbusy_list));
1569
1570 if (!list_empty(pbusy_list)) {
1571 pasync_handle = list_entry(pbusy_list->next,
1572 struct async_pdu_handle,
1573 link);
1574 WARN_ON(!pasync_handle);
1575 pasync_handle->consumed = 1;
1576 }
1577
1578 writables++;
1579 }
1580
1581 if (!writables) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05301582 beiscsi_log(phba, KERN_ERR,
1583 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1584 "BM_%d : Duplicate notification received - index 0x%x!!\n",
1585 cq_index);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301586 WARN_ON(1);
1587 }
1588
1589 *pwritables = *pwritables + writables;
1590 return 0;
1591}
1592
Jayamohan Kallickal9728d8d2012-04-03 23:41:47 -05001593static void hwi_free_async_msg(struct beiscsi_hba *phba,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301594 unsigned int cri)
1595{
1596 struct hwi_controller *phwi_ctrlr;
1597 struct hwi_async_pdu_context *pasync_ctx;
1598 struct async_pdu_handle *pasync_handle, *tmp_handle;
1599 struct list_head *plist;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301600
1601 phwi_ctrlr = phba->phwi_ctrlr;
1602 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1603
1604 plist = &pasync_ctx->async_entry[cri].wait_queue.list;
1605
1606 list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {
1607 list_del(&pasync_handle->link);
1608
Jayamohan Kallickal9728d8d2012-04-03 23:41:47 -05001609 if (pasync_handle->is_header) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301610 list_add_tail(&pasync_handle->link,
1611 &pasync_ctx->async_header.free_list);
1612 pasync_ctx->async_header.free_entries++;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301613 } else {
1614 list_add_tail(&pasync_handle->link,
1615 &pasync_ctx->async_data.free_list);
1616 pasync_ctx->async_data.free_entries++;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301617 }
1618 }
1619
1620 INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list);
1621 pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0;
1622 pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301623}
1624
1625static struct phys_addr *
1626hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx,
1627 unsigned int is_header, unsigned int host_write_ptr)
1628{
1629 struct phys_addr *pasync_sge = NULL;
1630
1631 if (is_header)
1632 pasync_sge = pasync_ctx->async_header.ring_base;
1633 else
1634 pasync_sge = pasync_ctx->async_data.ring_base;
1635
1636 return pasync_sge + host_write_ptr;
1637}
1638
1639static void hwi_post_async_buffers(struct beiscsi_hba *phba,
1640 unsigned int is_header)
1641{
1642 struct hwi_controller *phwi_ctrlr;
1643 struct hwi_async_pdu_context *pasync_ctx;
1644 struct async_pdu_handle *pasync_handle;
1645 struct list_head *pfree_link, *pbusy_list;
1646 struct phys_addr *pasync_sge;
1647 unsigned int ring_id, num_entries;
1648 unsigned int host_write_num;
1649 unsigned int writables;
1650 unsigned int i = 0;
1651 u32 doorbell = 0;
1652
1653 phwi_ctrlr = phba->phwi_ctrlr;
1654 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05001655 num_entries = pasync_ctx->num_entries;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301656
1657 if (is_header) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301658 writables = min(pasync_ctx->async_header.writables,
1659 pasync_ctx->async_header.free_entries);
1660 pfree_link = pasync_ctx->async_header.free_list.next;
1661 host_write_num = pasync_ctx->async_header.host_write_ptr;
1662 ring_id = phwi_ctrlr->default_pdu_hdr.id;
1663 } else {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301664 writables = min(pasync_ctx->async_data.writables,
1665 pasync_ctx->async_data.free_entries);
1666 pfree_link = pasync_ctx->async_data.free_list.next;
1667 host_write_num = pasync_ctx->async_data.host_write_ptr;
1668 ring_id = phwi_ctrlr->default_pdu_data.id;
1669 }
1670
1671 writables = (writables / 8) * 8;
1672 if (writables) {
1673 for (i = 0; i < writables; i++) {
1674 pbusy_list =
1675 hwi_get_async_busy_list(pasync_ctx, is_header,
1676 host_write_num);
1677 pasync_handle =
1678 list_entry(pfree_link, struct async_pdu_handle,
1679 link);
1680 WARN_ON(!pasync_handle);
1681 pasync_handle->consumed = 0;
1682
1683 pfree_link = pfree_link->next;
1684
1685 pasync_sge = hwi_get_ring_address(pasync_ctx,
1686 is_header, host_write_num);
1687
1688 pasync_sge->hi = pasync_handle->pa.u.a32.address_lo;
1689 pasync_sge->lo = pasync_handle->pa.u.a32.address_hi;
1690
1691 list_move(&pasync_handle->link, pbusy_list);
1692
1693 host_write_num++;
1694 host_write_num = host_write_num % num_entries;
1695 }
1696
1697 if (is_header) {
1698 pasync_ctx->async_header.host_write_ptr =
1699 host_write_num;
1700 pasync_ctx->async_header.free_entries -= writables;
1701 pasync_ctx->async_header.writables -= writables;
1702 pasync_ctx->async_header.busy_entries += writables;
1703 } else {
1704 pasync_ctx->async_data.host_write_ptr = host_write_num;
1705 pasync_ctx->async_data.free_entries -= writables;
1706 pasync_ctx->async_data.writables -= writables;
1707 pasync_ctx->async_data.busy_entries += writables;
1708 }
1709
1710 doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK;
1711 doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT;
1712 doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT;
1713 doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK)
1714 << DB_DEF_PDU_CQPROC_SHIFT;
1715
1716 iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET);
1717 }
1718}
1719
1720static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba,
1721 struct beiscsi_conn *beiscsi_conn,
1722 struct i_t_dpdu_cqe *pdpdu_cqe)
1723{
1724 struct hwi_controller *phwi_ctrlr;
1725 struct hwi_async_pdu_context *pasync_ctx;
1726 struct async_pdu_handle *pasync_handle = NULL;
1727 unsigned int cq_index = -1;
1728
1729 phwi_ctrlr = phba->phwi_ctrlr;
1730 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1731
1732 pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
1733 pdpdu_cqe, &cq_index);
1734 BUG_ON(pasync_handle->is_header != 0);
1735 if (pasync_handle->consumed == 0)
John Soni Jose99bc5d52012-08-20 23:00:18 +05301736 hwi_update_async_writables(phba, pasync_ctx,
1737 pasync_handle->is_header, cq_index);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301738
1739 hwi_free_async_msg(phba, pasync_handle->cri);
1740 hwi_post_async_buffers(phba, pasync_handle->is_header);
1741}
1742
1743static unsigned int
1744hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,
1745 struct beiscsi_hba *phba,
1746 struct hwi_async_pdu_context *pasync_ctx, unsigned short cri)
1747{
1748 struct list_head *plist;
1749 struct async_pdu_handle *pasync_handle;
1750 void *phdr = NULL;
1751 unsigned int hdr_len = 0, buf_len = 0;
1752 unsigned int status, index = 0, offset = 0;
1753 void *pfirst_buffer = NULL;
1754 unsigned int num_buf = 0;
1755
1756 plist = &pasync_ctx->async_entry[cri].wait_queue.list;
1757
1758 list_for_each_entry(pasync_handle, plist, link) {
1759 if (index == 0) {
1760 phdr = pasync_handle->pbuffer;
1761 hdr_len = pasync_handle->buffer_len;
1762 } else {
1763 buf_len = pasync_handle->buffer_len;
1764 if (!num_buf) {
1765 pfirst_buffer = pasync_handle->pbuffer;
1766 num_buf++;
1767 }
1768 memcpy(pfirst_buffer + offset,
1769 pasync_handle->pbuffer, buf_len);
Jayamohan Kallickalf2ba02b2012-04-03 23:41:37 -05001770 offset += buf_len;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301771 }
1772 index++;
1773 }
1774
1775 status = beiscsi_process_async_pdu(beiscsi_conn, phba,
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05301776 (beiscsi_conn->beiscsi_conn_cid -
1777 phba->fw_config.iscsi_cid_start),
1778 phdr, hdr_len, pfirst_buffer,
Jayamohan Kallickalf2ba02b2012-04-03 23:41:37 -05001779 offset);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301780
Jayamohan Kallickal605c6cd2012-04-03 23:41:48 -05001781 hwi_free_async_msg(phba, cri);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301782 return 0;
1783}
1784
1785static unsigned int
1786hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn,
1787 struct beiscsi_hba *phba,
1788 struct async_pdu_handle *pasync_handle)
1789{
1790 struct hwi_async_pdu_context *pasync_ctx;
1791 struct hwi_controller *phwi_ctrlr;
1792 unsigned int bytes_needed = 0, status = 0;
1793 unsigned short cri = pasync_handle->cri;
1794 struct pdu_base *ppdu;
1795
1796 phwi_ctrlr = phba->phwi_ctrlr;
1797 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1798
1799 list_del(&pasync_handle->link);
1800 if (pasync_handle->is_header) {
1801 pasync_ctx->async_header.busy_entries--;
1802 if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
1803 hwi_free_async_msg(phba, cri);
1804 BUG();
1805 }
1806
1807 pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0;
1808 pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1;
1809 pasync_ctx->async_entry[cri].wait_queue.hdr_len =
1810 (unsigned short)pasync_handle->buffer_len;
1811 list_add_tail(&pasync_handle->link,
1812 &pasync_ctx->async_entry[cri].wait_queue.list);
1813
1814 ppdu = pasync_handle->pbuffer;
1815 bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base,
1816 data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) &
1817 0xFFFF0000) | ((be16_to_cpu((ppdu->
1818 dw[offsetof(struct amap_pdu_base, data_len_lo) / 32]
1819 & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF));
1820
1821 if (status == 0) {
1822 pasync_ctx->async_entry[cri].wait_queue.bytes_needed =
1823 bytes_needed;
1824
1825 if (bytes_needed == 0)
1826 status = hwi_fwd_async_msg(beiscsi_conn, phba,
1827 pasync_ctx, cri);
1828 }
1829 } else {
1830 pasync_ctx->async_data.busy_entries--;
1831 if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) {
1832 list_add_tail(&pasync_handle->link,
1833 &pasync_ctx->async_entry[cri].wait_queue.
1834 list);
1835 pasync_ctx->async_entry[cri].wait_queue.
1836 bytes_received +=
1837 (unsigned short)pasync_handle->buffer_len;
1838
1839 if (pasync_ctx->async_entry[cri].wait_queue.
1840 bytes_received >=
1841 pasync_ctx->async_entry[cri].wait_queue.
1842 bytes_needed)
1843 status = hwi_fwd_async_msg(beiscsi_conn, phba,
1844 pasync_ctx, cri);
1845 }
1846 }
1847 return status;
1848}
1849
1850static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
1851 struct beiscsi_hba *phba,
1852 struct i_t_dpdu_cqe *pdpdu_cqe)
1853{
1854 struct hwi_controller *phwi_ctrlr;
1855 struct hwi_async_pdu_context *pasync_ctx;
1856 struct async_pdu_handle *pasync_handle = NULL;
1857 unsigned int cq_index = -1;
1858
1859 phwi_ctrlr = phba->phwi_ctrlr;
1860 pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);
1861 pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,
1862 pdpdu_cqe, &cq_index);
1863
1864 if (pasync_handle->consumed == 0)
John Soni Jose99bc5d52012-08-20 23:00:18 +05301865 hwi_update_async_writables(phba, pasync_ctx,
1866 pasync_handle->is_header, cq_index);
1867
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301868 hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle);
1869 hwi_post_async_buffers(phba, pasync_handle->is_header);
1870}
1871
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05301872static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
1873{
1874 struct be_queue_info *mcc_cq;
1875 struct be_mcc_compl *mcc_compl;
1876 unsigned int num_processed = 0;
1877
1878 mcc_cq = &phba->ctrl.mcc_obj.cq;
1879 mcc_compl = queue_tail_node(mcc_cq);
1880 mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
1881 while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) {
1882
1883 if (num_processed >= 32) {
1884 hwi_ring_cq_db(phba, mcc_cq->id,
1885 num_processed, 0, 0);
1886 num_processed = 0;
1887 }
1888 if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) {
1889 /* Interpret flags as an async trailer */
1890 if (is_link_state_evt(mcc_compl->flags))
1891 /* Interpret compl as a async link evt */
1892 beiscsi_async_link_state_process(phba,
1893 (struct be_async_event_link_state *) mcc_compl);
1894 else
John Soni Jose99bc5d52012-08-20 23:00:18 +05301895 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX,
1896 "BM_%d : Unsupported Async Event, flags"
1897 " = 0x%08x\n",
1898 mcc_compl->flags);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05301899 } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
1900 be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
1901 atomic_dec(&phba->ctrl.mcc_obj.q.used);
1902 }
1903
1904 mcc_compl->flags = 0;
1905 queue_tail_inc(mcc_cq);
1906 mcc_compl = queue_tail_node(mcc_cq);
1907 mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
1908 num_processed++;
1909 }
1910
1911 if (num_processed > 0)
1912 hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0);
1913
1914}
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301915
1916static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301917{
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301918 struct be_queue_info *cq;
1919 struct sol_cqe *sol;
1920 struct dmsg_cqe *dmsg;
1921 unsigned int num_processed = 0;
1922 unsigned int tot_nump = 0;
1923 struct beiscsi_conn *beiscsi_conn;
Jayamohan Kallickalc2462282010-01-05 05:05:34 +05301924 struct beiscsi_endpoint *beiscsi_ep;
1925 struct iscsi_endpoint *ep;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301926 struct beiscsi_hba *phba;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301927
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301928 cq = pbe_eq->cq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301929 sol = queue_tail_node(cq);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301930 phba = pbe_eq->phba;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301931
1932 while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] &
1933 CQE_VALID_MASK) {
1934 be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
1935
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301936 ep = phba->ep_array[(u32) ((sol->
Jayamohan Kallickalc2462282010-01-05 05:05:34 +05301937 dw[offsetof(struct amap_sol_cqe, cid) / 32] &
1938 SOL_CID_MASK) >> 6) -
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05301939 phba->fw_config.iscsi_cid_start];
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05301940
Jayamohan Kallickalc2462282010-01-05 05:05:34 +05301941 beiscsi_ep = ep->dd_data;
1942 beiscsi_conn = beiscsi_ep->conn;
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05301943
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301944 if (num_processed >= 32) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301945 hwi_ring_cq_db(phba, cq->id,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301946 num_processed, 0, 0);
1947 tot_nump += num_processed;
1948 num_processed = 0;
1949 }
1950
1951 switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) /
1952 32] & CQE_CODE_MASK) {
1953 case SOL_CMD_COMPLETE:
1954 hwi_complete_cmd(beiscsi_conn, phba, sol);
1955 break;
1956 case DRIVERMSG_NOTIFY:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301957 beiscsi_log(phba, KERN_INFO,
1958 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1959 "BM_%d : Received DRIVERMSG_NOTIFY\n");
1960
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301961 dmsg = (struct dmsg_cqe *)sol;
1962 hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);
1963 break;
1964 case UNSOL_HDR_NOTIFY:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301965 beiscsi_log(phba, KERN_INFO,
1966 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1967 "BM_%d : Received UNSOL_HDR_ NOTIFY\n");
1968
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05301969 hwi_process_default_pdu_ring(beiscsi_conn, phba,
1970 (struct i_t_dpdu_cqe *)sol);
1971 break;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301972 case UNSOL_DATA_NOTIFY:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301973 beiscsi_log(phba, KERN_INFO,
1974 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1975 "BM_%d : Received UNSOL_DATA_NOTIFY\n");
1976
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301977 hwi_process_default_pdu_ring(beiscsi_conn, phba,
1978 (struct i_t_dpdu_cqe *)sol);
1979 break;
1980 case CXN_INVALIDATE_INDEX_NOTIFY:
1981 case CMD_INVALIDATED_NOTIFY:
1982 case CXN_INVALIDATE_NOTIFY:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301983 beiscsi_log(phba, KERN_ERR,
1984 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
1985 "BM_%d : Ignoring CQ Error notification for"
1986 " cmd/cxn invalidate\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05301987 break;
1988 case SOL_CMD_KILLED_DATA_DIGEST_ERR:
1989 case CMD_KILLED_INVALID_STATSN_RCVD:
1990 case CMD_KILLED_INVALID_R2T_RCVD:
1991 case CMD_CXN_KILLED_LUN_INVALID:
1992 case CMD_CXN_KILLED_ICD_INVALID:
1993 case CMD_CXN_KILLED_ITT_INVALID:
1994 case CMD_CXN_KILLED_SEQ_OUTOFORDER:
1995 case CMD_CXN_KILLED_INVALID_DATASN_RCVD:
John Soni Jose99bc5d52012-08-20 23:00:18 +05301996 beiscsi_log(phba, KERN_ERR,
1997 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
1998 "BM_%d : CQ Error notification for cmd.. "
1999 "code %d cid 0x%x\n",
2000 sol->dw[offsetof(struct amap_sol_cqe,
2001 code) / 32] & CQE_CODE_MASK,
2002 sol->dw[offsetof(struct amap_sol_cqe,
2003 cid) / 32] & SOL_CID_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302004 break;
2005 case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
John Soni Jose99bc5d52012-08-20 23:00:18 +05302006 beiscsi_log(phba, KERN_ERR,
2007 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
2008 "BM_%d : Digest error on def pdu ring,"
2009 " dropping..\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302010 hwi_flush_default_pdu_buffer(phba, beiscsi_conn,
2011 (struct i_t_dpdu_cqe *) sol);
2012 break;
2013 case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL:
2014 case CXN_KILLED_BURST_LEN_MISMATCH:
2015 case CXN_KILLED_AHS_RCVD:
2016 case CXN_KILLED_HDR_DIGEST_ERR:
2017 case CXN_KILLED_UNKNOWN_HDR:
2018 case CXN_KILLED_STALE_ITT_TTT_RCVD:
2019 case CXN_KILLED_INVALID_ITT_TTT_RCVD:
2020 case CXN_KILLED_TIMED_OUT:
2021 case CXN_KILLED_FIN_RCVD:
2022 case CXN_KILLED_BAD_UNSOL_PDU_RCVD:
2023 case CXN_KILLED_BAD_WRB_INDEX_ERROR:
2024 case CXN_KILLED_OVER_RUN_RESIDUAL:
2025 case CXN_KILLED_UNDER_RUN_RESIDUAL:
2026 case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN:
John Soni Jose99bc5d52012-08-20 23:00:18 +05302027 beiscsi_log(phba, KERN_ERR,
2028 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
2029 "BM_%d : CQ Error %d, reset CID 0x%x...\n",
2030 sol->dw[offsetof(struct amap_sol_cqe,
2031 code) / 32] & CQE_CODE_MASK,
2032 sol->dw[offsetof(struct amap_sol_cqe,
2033 cid) / 32] & CQE_CID_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302034 iscsi_conn_failure(beiscsi_conn->conn,
2035 ISCSI_ERR_CONN_FAILED);
2036 break;
2037 case CXN_KILLED_RST_SENT:
2038 case CXN_KILLED_RST_RCVD:
John Soni Jose99bc5d52012-08-20 23:00:18 +05302039 beiscsi_log(phba, KERN_ERR,
2040 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
2041 "BM_%d : CQ Error %d, reset"
2042 "received/sent on CID 0x%x...\n",
2043 sol->dw[offsetof(struct amap_sol_cqe,
2044 code) / 32] & CQE_CODE_MASK,
2045 sol->dw[offsetof(struct amap_sol_cqe,
2046 cid) / 32] & CQE_CID_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302047 iscsi_conn_failure(beiscsi_conn->conn,
2048 ISCSI_ERR_CONN_FAILED);
2049 break;
2050 default:
John Soni Jose99bc5d52012-08-20 23:00:18 +05302051 beiscsi_log(phba, KERN_ERR,
2052 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
2053 "BM_%d : CQ Error Invalid code= %d "
2054 "received on CID 0x%x...\n",
2055 sol->dw[offsetof(struct amap_sol_cqe,
2056 code) / 32] & CQE_CODE_MASK,
2057 sol->dw[offsetof(struct amap_sol_cqe,
2058 cid) / 32] & CQE_CID_MASK);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302059 break;
2060 }
2061
2062 AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0);
2063 queue_tail_inc(cq);
2064 sol = queue_tail_node(cq);
2065 num_processed++;
2066 }
2067
2068 if (num_processed > 0) {
2069 tot_nump += num_processed;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302070 hwi_ring_cq_db(phba, cq->id, num_processed, 1, 0);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302071 }
2072 return tot_nump;
2073}
2074
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05302075void beiscsi_process_all_cqs(struct work_struct *work)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302076{
2077 unsigned long flags;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302078 struct hwi_controller *phwi_ctrlr;
2079 struct hwi_context_memory *phwi_context;
2080 struct be_eq_obj *pbe_eq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302081 struct beiscsi_hba *phba =
2082 container_of(work, struct beiscsi_hba, work_cqs);
2083
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302084 phwi_ctrlr = phba->phwi_ctrlr;
2085 phwi_context = phwi_ctrlr->phwi_ctxt;
2086 if (phba->msix_enabled)
2087 pbe_eq = &phwi_context->be_eq[phba->num_cpus];
2088 else
2089 pbe_eq = &phwi_context->be_eq[0];
2090
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302091 if (phba->todo_mcc_cq) {
2092 spin_lock_irqsave(&phba->isr_lock, flags);
2093 phba->todo_mcc_cq = 0;
2094 spin_unlock_irqrestore(&phba->isr_lock, flags);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05302095 beiscsi_process_mcc_isr(phba);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302096 }
2097
2098 if (phba->todo_cq) {
2099 spin_lock_irqsave(&phba->isr_lock, flags);
2100 phba->todo_cq = 0;
2101 spin_unlock_irqrestore(&phba->isr_lock, flags);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302102 beiscsi_process_cq(pbe_eq);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302103 }
2104}
2105
2106static int be_iopoll(struct blk_iopoll *iop, int budget)
2107{
2108 static unsigned int ret;
2109 struct beiscsi_hba *phba;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302110 struct be_eq_obj *pbe_eq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302111
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302112 pbe_eq = container_of(iop, struct be_eq_obj, iopoll);
2113 ret = beiscsi_process_cq(pbe_eq);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302114 if (ret < budget) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302115 phba = pbe_eq->phba;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302116 blk_iopoll_complete(iop);
John Soni Jose99bc5d52012-08-20 23:00:18 +05302117 beiscsi_log(phba, KERN_INFO,
2118 BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
2119 "BM_%d : rearm pbe_eq->q.id =%d\n",
2120 pbe_eq->q.id);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302121 hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302122 }
2123 return ret;
2124}
2125
2126static void
2127hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
2128 unsigned int num_sg, struct beiscsi_io_task *io_task)
2129{
2130 struct iscsi_sge *psgl;
Jayamohan Kallickal58ff4bd2010-10-06 23:46:47 +05302131 unsigned int sg_len, index;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302132 unsigned int sge_len = 0;
2133 unsigned long long addr;
2134 struct scatterlist *l_sg;
2135 unsigned int offset;
2136
2137 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
2138 io_task->bhs_pa.u.a32.address_lo);
2139 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
2140 io_task->bhs_pa.u.a32.address_hi);
2141
2142 l_sg = sg;
Jayamohan Kallickal48bd86c2010-01-07 01:50:19 +05302143 for (index = 0; (index < num_sg) && (index < 2); index++,
2144 sg = sg_next(sg)) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302145 if (index == 0) {
2146 sg_len = sg_dma_len(sg);
2147 addr = (u64) sg_dma_address(sg);
2148 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302149 ((u32)(addr & 0xFFFFFFFF)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302150 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302151 ((u32)(addr >> 32)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302152 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
2153 sg_len);
2154 sge_len = sg_len;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302155 } else {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302156 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset,
2157 pwrb, sge_len);
2158 sg_len = sg_dma_len(sg);
2159 addr = (u64) sg_dma_address(sg);
2160 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302161 ((u32)(addr & 0xFFFFFFFF)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302162 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302163 ((u32)(addr >> 32)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302164 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb,
2165 sg_len);
2166 }
2167 }
2168 psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
2169 memset(psgl, 0, sizeof(*psgl) * BE2_SGE);
2170
2171 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2);
2172
2173 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
2174 io_task->bhs_pa.u.a32.address_hi);
2175 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
2176 io_task->bhs_pa.u.a32.address_lo);
2177
Jayamohan Kallickalcaf818f2010-01-23 05:38:18 +05302178 if (num_sg == 1) {
2179 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
2180 1);
2181 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
2182 0);
2183 } else if (num_sg == 2) {
2184 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
2185 0);
2186 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
2187 1);
2188 } else {
2189 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb,
2190 0);
2191 AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb,
2192 0);
2193 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302194 sg = l_sg;
2195 psgl++;
2196 psgl++;
2197 offset = 0;
Jayamohan Kallickal48bd86c2010-01-07 01:50:19 +05302198 for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302199 sg_len = sg_dma_len(sg);
2200 addr = (u64) sg_dma_address(sg);
2201 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
2202 (addr & 0xFFFFFFFF));
2203 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
2204 (addr >> 32));
2205 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len);
2206 AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset);
2207 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
2208 offset += sg_len;
2209 }
2210 psgl--;
2211 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
2212}
2213
2214static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
2215{
2216 struct iscsi_sge *psgl;
2217 unsigned long long addr;
2218 struct beiscsi_io_task *io_task = task->dd_data;
2219 struct beiscsi_conn *beiscsi_conn = io_task->conn;
2220 struct beiscsi_hba *phba = beiscsi_conn->phba;
2221
2222 io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;
2223 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb,
2224 io_task->bhs_pa.u.a32.address_lo);
2225 AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb,
2226 io_task->bhs_pa.u.a32.address_hi);
2227
2228 if (task->data) {
2229 if (task->data_count) {
2230 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
2231 addr = (u64) pci_map_single(phba->pcidev,
2232 task->data,
2233 task->data_count, 1);
2234 } else {
2235 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
2236 addr = 0;
2237 }
2238 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302239 ((u32)(addr & 0xFFFFFFFF)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302240 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302241 ((u32)(addr >> 32)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302242 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,
2243 task->data_count);
2244
2245 AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);
2246 } else {
2247 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
2248 addr = 0;
2249 }
2250
2251 psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag;
2252
2253 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len);
2254
2255 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
2256 io_task->bhs_pa.u.a32.address_hi);
2257 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
2258 io_task->bhs_pa.u.a32.address_lo);
2259 if (task->data) {
2260 psgl++;
2261 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 0);
2262 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 0);
2263 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0);
2264 AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, 0);
2265 AMAP_SET_BITS(struct amap_iscsi_sge, rsvd0, psgl, 0);
2266 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0);
2267
2268 psgl++;
2269 if (task->data) {
2270 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302271 ((u32)(addr & 0xFFFFFFFF)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302272 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302273 ((u32)(addr >> 32)));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302274 }
2275 AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
2276 }
2277 AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
2278}
2279
2280static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
2281{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302282 unsigned int num_cq_pages, num_async_pdu_buf_pages;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302283 unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;
2284 unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;
2285
2286 num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
2287 sizeof(struct sol_cqe));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302288 num_async_pdu_buf_pages =
2289 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
2290 phba->params.defpdu_hdr_sz);
2291 num_async_pdu_buf_sgl_pages =
2292 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
2293 sizeof(struct phys_addr));
2294 num_async_pdu_data_pages =
2295 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
2296 phba->params.defpdu_data_sz);
2297 num_async_pdu_data_sgl_pages =
2298 PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \
2299 sizeof(struct phys_addr));
2300
2301 phba->params.hwi_ws_sz = sizeof(struct hwi_controller);
2302
2303 phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 *
2304 BE_ISCSI_PDU_HEADER_SIZE;
2305 phba->mem_req[HWI_MEM_ADDN_CONTEXT] =
2306 sizeof(struct hwi_context_memory);
2307
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302308
2309 phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb)
2310 * (phba->params.wrbs_per_cxn)
2311 * phba->params.cxns_per_ctrl;
2312 wrb_sz_per_cxn = sizeof(struct wrb_handle) *
2313 (phba->params.wrbs_per_cxn);
2314 phba->mem_req[HWI_MEM_WRBH] = roundup_pow_of_two((wrb_sz_per_cxn) *
2315 phba->params.cxns_per_ctrl);
2316
2317 phba->mem_req[HWI_MEM_SGLH] = sizeof(struct sgl_handle) *
2318 phba->params.icds_per_ctrl;
2319 phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) *
2320 phba->params.num_sge_per_io * phba->params.icds_per_ctrl;
2321
2322 phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] =
2323 num_async_pdu_buf_pages * PAGE_SIZE;
2324 phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] =
2325 num_async_pdu_data_pages * PAGE_SIZE;
2326 phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] =
2327 num_async_pdu_buf_sgl_pages * PAGE_SIZE;
2328 phba->mem_req[HWI_MEM_ASYNC_DATA_RING] =
2329 num_async_pdu_data_sgl_pages * PAGE_SIZE;
2330 phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] =
2331 phba->params.asyncpdus_per_ctrl *
2332 sizeof(struct async_pdu_handle);
2333 phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] =
2334 phba->params.asyncpdus_per_ctrl *
2335 sizeof(struct async_pdu_handle);
2336 phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] =
2337 sizeof(struct hwi_async_pdu_context) +
2338 (phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry));
2339}
2340
2341static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
2342{
2343 struct be_mem_descriptor *mem_descr;
2344 dma_addr_t bus_add;
2345 struct mem_array *mem_arr, *mem_arr_orig;
2346 unsigned int i, j, alloc_size, curr_alloc_size;
2347
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002348 phba->phwi_ctrlr = kzalloc(phba->params.hwi_ws_sz, GFP_KERNEL);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302349 if (!phba->phwi_ctrlr)
2350 return -ENOMEM;
2351
2352 phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
2353 GFP_KERNEL);
2354 if (!phba->init_mem) {
2355 kfree(phba->phwi_ctrlr);
2356 return -ENOMEM;
2357 }
2358
2359 mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT,
2360 GFP_KERNEL);
2361 if (!mem_arr_orig) {
2362 kfree(phba->init_mem);
2363 kfree(phba->phwi_ctrlr);
2364 return -ENOMEM;
2365 }
2366
2367 mem_descr = phba->init_mem;
2368 for (i = 0; i < SE_MEM_MAX; i++) {
2369 j = 0;
2370 mem_arr = mem_arr_orig;
2371 alloc_size = phba->mem_req[i];
2372 memset(mem_arr, 0, sizeof(struct mem_array) *
2373 BEISCSI_MAX_FRAGS_INIT);
2374 curr_alloc_size = min(be_max_phys_size * 1024, alloc_size);
2375 do {
2376 mem_arr->virtual_address = pci_alloc_consistent(
2377 phba->pcidev,
2378 curr_alloc_size,
2379 &bus_add);
2380 if (!mem_arr->virtual_address) {
2381 if (curr_alloc_size <= BE_MIN_MEM_SIZE)
2382 goto free_mem;
2383 if (curr_alloc_size -
2384 rounddown_pow_of_two(curr_alloc_size))
2385 curr_alloc_size = rounddown_pow_of_two
2386 (curr_alloc_size);
2387 else
2388 curr_alloc_size = curr_alloc_size / 2;
2389 } else {
2390 mem_arr->bus_address.u.
2391 a64.address = (__u64) bus_add;
2392 mem_arr->size = curr_alloc_size;
2393 alloc_size -= curr_alloc_size;
2394 curr_alloc_size = min(be_max_phys_size *
2395 1024, alloc_size);
2396 j++;
2397 mem_arr++;
2398 }
2399 } while (alloc_size);
2400 mem_descr->num_elements = j;
2401 mem_descr->size_in_bytes = phba->mem_req[i];
2402 mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j,
2403 GFP_KERNEL);
2404 if (!mem_descr->mem_array)
2405 goto free_mem;
2406
2407 memcpy(mem_descr->mem_array, mem_arr_orig,
2408 sizeof(struct mem_array) * j);
2409 mem_descr++;
2410 }
2411 kfree(mem_arr_orig);
2412 return 0;
2413free_mem:
2414 mem_descr->num_elements = j;
2415 while ((i) || (j)) {
2416 for (j = mem_descr->num_elements; j > 0; j--) {
2417 pci_free_consistent(phba->pcidev,
2418 mem_descr->mem_array[j - 1].size,
2419 mem_descr->mem_array[j - 1].
2420 virtual_address,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302421 (unsigned long)mem_descr->
2422 mem_array[j - 1].
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302423 bus_address.u.a64.address);
2424 }
2425 if (i) {
2426 i--;
2427 kfree(mem_descr->mem_array);
2428 mem_descr--;
2429 }
2430 }
2431 kfree(mem_arr_orig);
2432 kfree(phba->init_mem);
2433 kfree(phba->phwi_ctrlr);
2434 return -ENOMEM;
2435}
2436
2437static int beiscsi_get_memory(struct beiscsi_hba *phba)
2438{
2439 beiscsi_find_mem_req(phba);
2440 return beiscsi_alloc_mem(phba);
2441}
2442
2443static void iscsi_init_global_templates(struct beiscsi_hba *phba)
2444{
2445 struct pdu_data_out *pdata_out;
2446 struct pdu_nop_out *pnop_out;
2447 struct be_mem_descriptor *mem_descr;
2448
2449 mem_descr = phba->init_mem;
2450 mem_descr += ISCSI_MEM_GLOBAL_HEADER;
2451 pdata_out =
2452 (struct pdu_data_out *)mem_descr->mem_array[0].virtual_address;
2453 memset(pdata_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
2454
2455 AMAP_SET_BITS(struct amap_pdu_data_out, opcode, pdata_out,
2456 IIOC_SCSI_DATA);
2457
2458 pnop_out =
2459 (struct pdu_nop_out *)((unsigned char *)mem_descr->mem_array[0].
2460 virtual_address + BE_ISCSI_PDU_HEADER_SIZE);
2461
2462 memset(pnop_out, 0, BE_ISCSI_PDU_HEADER_SIZE);
2463 AMAP_SET_BITS(struct amap_pdu_nop_out, ttt, pnop_out, 0xFFFFFFFF);
2464 AMAP_SET_BITS(struct amap_pdu_nop_out, f_bit, pnop_out, 1);
2465 AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0);
2466}
2467
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002468static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302469{
2470 struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb;
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002471 struct wrb_handle *pwrb_handle = NULL;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302472 struct hwi_controller *phwi_ctrlr;
2473 struct hwi_wrb_context *pwrb_context;
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002474 struct iscsi_wrb *pwrb = NULL;
2475 unsigned int num_cxn_wrbh = 0;
2476 unsigned int num_cxn_wrb = 0, j, idx = 0, index;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302477
2478 mem_descr_wrbh = phba->init_mem;
2479 mem_descr_wrbh += HWI_MEM_WRBH;
2480
2481 mem_descr_wrb = phba->init_mem;
2482 mem_descr_wrb += HWI_MEM_WRB;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302483 phwi_ctrlr = phba->phwi_ctrlr;
2484
2485 for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
2486 pwrb_context = &phwi_ctrlr->wrb_context[index];
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302487 pwrb_context->pwrb_handle_base =
2488 kzalloc(sizeof(struct wrb_handle *) *
2489 phba->params.wrbs_per_cxn, GFP_KERNEL);
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002490 if (!pwrb_context->pwrb_handle_base) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302491 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2492 "BM_%d : Mem Alloc Failed. Failing to load\n");
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002493 goto init_wrb_hndl_failed;
2494 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302495 pwrb_context->pwrb_handle_basestd =
2496 kzalloc(sizeof(struct wrb_handle *) *
2497 phba->params.wrbs_per_cxn, GFP_KERNEL);
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002498 if (!pwrb_context->pwrb_handle_basestd) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302499 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2500 "BM_%d : Mem Alloc Failed. Failing to load\n");
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002501 goto init_wrb_hndl_failed;
2502 }
2503 if (!num_cxn_wrbh) {
2504 pwrb_handle =
2505 mem_descr_wrbh->mem_array[idx].virtual_address;
2506 num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) /
2507 ((sizeof(struct wrb_handle)) *
2508 phba->params.wrbs_per_cxn));
2509 idx++;
2510 }
2511 pwrb_context->alloc_index = 0;
2512 pwrb_context->wrb_handles_available = 0;
2513 pwrb_context->free_index = 0;
2514
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302515 if (num_cxn_wrbh) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302516 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
2517 pwrb_context->pwrb_handle_base[j] = pwrb_handle;
2518 pwrb_context->pwrb_handle_basestd[j] =
2519 pwrb_handle;
2520 pwrb_context->wrb_handles_available++;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302521 pwrb_handle->wrb_index = j;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302522 pwrb_handle++;
2523 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302524 num_cxn_wrbh--;
2525 }
2526 }
2527 idx = 0;
Jayamohan Kallickaled58ea22010-02-20 08:05:07 +05302528 for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302529 pwrb_context = &phwi_ctrlr->wrb_context[index];
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002530 if (!num_cxn_wrb) {
2531 pwrb = mem_descr_wrb->mem_array[idx].virtual_address;
2532 num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) /
2533 ((sizeof(struct iscsi_wrb) *
2534 phba->params.wrbs_per_cxn));
2535 idx++;
2536 }
2537
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302538 if (num_cxn_wrb) {
2539 for (j = 0; j < phba->params.wrbs_per_cxn; j++) {
2540 pwrb_handle = pwrb_context->pwrb_handle_base[j];
2541 pwrb_handle->pwrb = pwrb;
2542 pwrb++;
2543 }
2544 num_cxn_wrb--;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302545 }
2546 }
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05002547 return 0;
2548init_wrb_hndl_failed:
2549 for (j = index; j > 0; j--) {
2550 pwrb_context = &phwi_ctrlr->wrb_context[j];
2551 kfree(pwrb_context->pwrb_handle_base);
2552 kfree(pwrb_context->pwrb_handle_basestd);
2553 }
2554 return -ENOMEM;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302555}
2556
2557static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
2558{
2559 struct hwi_controller *phwi_ctrlr;
2560 struct hba_parameters *p = &phba->params;
2561 struct hwi_async_pdu_context *pasync_ctx;
2562 struct async_pdu_handle *pasync_header_h, *pasync_data_h;
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002563 unsigned int index, idx, num_per_mem, num_async_data;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302564 struct be_mem_descriptor *mem_descr;
2565
2566 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2567 mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT;
2568
2569 phwi_ctrlr = phba->phwi_ctrlr;
2570 phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *)
2571 mem_descr->mem_array[0].virtual_address;
2572 pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx;
2573 memset(pasync_ctx, 0, sizeof(*pasync_ctx));
2574
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002575 pasync_ctx->num_entries = p->asyncpdus_per_ctrl;
2576 pasync_ctx->buffer_size = p->defpdu_hdr_sz;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302577
2578 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2579 mem_descr += HWI_MEM_ASYNC_HEADER_BUF;
2580 if (mem_descr->mem_array[0].virtual_address) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302581 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2582 "BM_%d : hwi_init_async_pdu_ctx"
2583 " HWI_MEM_ASYNC_HEADER_BUF va=%p\n",
2584 mem_descr->mem_array[0].virtual_address);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302585 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05302586 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2587 "BM_%d : No Virtual address\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302588
2589 pasync_ctx->async_header.va_base =
2590 mem_descr->mem_array[0].virtual_address;
2591
2592 pasync_ctx->async_header.pa_base.u.a64.address =
2593 mem_descr->mem_array[0].bus_address.u.a64.address;
2594
2595 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2596 mem_descr += HWI_MEM_ASYNC_HEADER_RING;
2597 if (mem_descr->mem_array[0].virtual_address) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302598 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2599 "BM_%d : hwi_init_async_pdu_ctx"
2600 " HWI_MEM_ASYNC_HEADER_RING va=%p\n",
2601 mem_descr->mem_array[0].virtual_address);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302602 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05302603 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2604 "BM_%d : No Virtual address\n");
2605
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302606 pasync_ctx->async_header.ring_base =
2607 mem_descr->mem_array[0].virtual_address;
2608
2609 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2610 mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE;
2611 if (mem_descr->mem_array[0].virtual_address) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302612 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2613 "BM_%d : hwi_init_async_pdu_ctx"
2614 " HWI_MEM_ASYNC_HEADER_HANDLE va=%p\n",
2615 mem_descr->mem_array[0].virtual_address);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302616 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05302617 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2618 "BM_%d : No Virtual address\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302619
2620 pasync_ctx->async_header.handle_base =
2621 mem_descr->mem_array[0].virtual_address;
2622 pasync_ctx->async_header.writables = 0;
2623 INIT_LIST_HEAD(&pasync_ctx->async_header.free_list);
2624
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302625
2626 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2627 mem_descr += HWI_MEM_ASYNC_DATA_RING;
2628 if (mem_descr->mem_array[0].virtual_address) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302629 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2630 "BM_%d : hwi_init_async_pdu_ctx"
2631 " HWI_MEM_ASYNC_DATA_RING va=%p\n",
2632 mem_descr->mem_array[0].virtual_address);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302633 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05302634 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2635 "BM_%d : No Virtual address\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302636
2637 pasync_ctx->async_data.ring_base =
2638 mem_descr->mem_array[0].virtual_address;
2639
2640 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2641 mem_descr += HWI_MEM_ASYNC_DATA_HANDLE;
2642 if (!mem_descr->mem_array[0].virtual_address)
John Soni Jose99bc5d52012-08-20 23:00:18 +05302643 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2644 "BM_%d : No Virtual address\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302645
2646 pasync_ctx->async_data.handle_base =
2647 mem_descr->mem_array[0].virtual_address;
2648 pasync_ctx->async_data.writables = 0;
2649 INIT_LIST_HEAD(&pasync_ctx->async_data.free_list);
2650
2651 pasync_header_h =
2652 (struct async_pdu_handle *)pasync_ctx->async_header.handle_base;
2653 pasync_data_h =
2654 (struct async_pdu_handle *)pasync_ctx->async_data.handle_base;
2655
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002656 mem_descr = (struct be_mem_descriptor *)phba->init_mem;
2657 mem_descr += HWI_MEM_ASYNC_DATA_BUF;
2658 if (mem_descr->mem_array[0].virtual_address) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302659 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2660 "BM_%d : hwi_init_async_pdu_ctx"
2661 " HWI_MEM_ASYNC_DATA_BUF va=%p\n",
2662 mem_descr->mem_array[0].virtual_address);
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002663 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05302664 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
2665 "BM_%d : No Virtual address\n");
2666
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002667 idx = 0;
2668 pasync_ctx->async_data.va_base =
2669 mem_descr->mem_array[idx].virtual_address;
2670 pasync_ctx->async_data.pa_base.u.a64.address =
2671 mem_descr->mem_array[idx].bus_address.u.a64.address;
2672
2673 num_async_data = ((mem_descr->mem_array[idx].size) /
2674 phba->params.defpdu_data_sz);
2675 num_per_mem = 0;
2676
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302677 for (index = 0; index < p->asyncpdus_per_ctrl; index++) {
2678 pasync_header_h->cri = -1;
2679 pasync_header_h->index = (char)index;
2680 INIT_LIST_HEAD(&pasync_header_h->link);
2681 pasync_header_h->pbuffer =
2682 (void *)((unsigned long)
2683 (pasync_ctx->async_header.va_base) +
2684 (p->defpdu_hdr_sz * index));
2685
2686 pasync_header_h->pa.u.a64.address =
2687 pasync_ctx->async_header.pa_base.u.a64.address +
2688 (p->defpdu_hdr_sz * index);
2689
2690 list_add_tail(&pasync_header_h->link,
2691 &pasync_ctx->async_header.free_list);
2692 pasync_header_h++;
2693 pasync_ctx->async_header.free_entries++;
2694 pasync_ctx->async_header.writables++;
2695
2696 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list);
2697 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].
2698 header_busy_list);
2699 pasync_data_h->cri = -1;
2700 pasync_data_h->index = (char)index;
2701 INIT_LIST_HEAD(&pasync_data_h->link);
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002702
2703 if (!num_async_data) {
2704 num_per_mem = 0;
2705 idx++;
2706 pasync_ctx->async_data.va_base =
2707 mem_descr->mem_array[idx].virtual_address;
2708 pasync_ctx->async_data.pa_base.u.a64.address =
2709 mem_descr->mem_array[idx].
2710 bus_address.u.a64.address;
2711
2712 num_async_data = ((mem_descr->mem_array[idx].size) /
2713 phba->params.defpdu_data_sz);
2714 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302715 pasync_data_h->pbuffer =
2716 (void *)((unsigned long)
2717 (pasync_ctx->async_data.va_base) +
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002718 (p->defpdu_data_sz * num_per_mem));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302719
2720 pasync_data_h->pa.u.a64.address =
2721 pasync_ctx->async_data.pa_base.u.a64.address +
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05002722 (p->defpdu_data_sz * num_per_mem);
2723 num_per_mem++;
2724 num_async_data--;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302725
2726 list_add_tail(&pasync_data_h->link,
2727 &pasync_ctx->async_data.free_list);
2728 pasync_data_h++;
2729 pasync_ctx->async_data.free_entries++;
2730 pasync_ctx->async_data.writables++;
2731
2732 INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list);
2733 }
2734
2735 pasync_ctx->async_header.host_write_ptr = 0;
2736 pasync_ctx->async_header.ep_read_ptr = -1;
2737 pasync_ctx->async_data.host_write_ptr = 0;
2738 pasync_ctx->async_data.ep_read_ptr = -1;
2739}
2740
2741static int
2742be_sgl_create_contiguous(void *virtual_address,
2743 u64 physical_address, u32 length,
2744 struct be_dma_mem *sgl)
2745{
2746 WARN_ON(!virtual_address);
2747 WARN_ON(!physical_address);
2748 WARN_ON(!length > 0);
2749 WARN_ON(!sgl);
2750
2751 sgl->va = virtual_address;
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302752 sgl->dma = (unsigned long)physical_address;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302753 sgl->size = length;
2754
2755 return 0;
2756}
2757
2758static void be_sgl_destroy_contiguous(struct be_dma_mem *sgl)
2759{
2760 memset(sgl, 0, sizeof(*sgl));
2761}
2762
2763static void
2764hwi_build_be_sgl_arr(struct beiscsi_hba *phba,
2765 struct mem_array *pmem, struct be_dma_mem *sgl)
2766{
2767 if (sgl->va)
2768 be_sgl_destroy_contiguous(sgl);
2769
2770 be_sgl_create_contiguous(pmem->virtual_address,
2771 pmem->bus_address.u.a64.address,
2772 pmem->size, sgl);
2773}
2774
2775static void
2776hwi_build_be_sgl_by_offset(struct beiscsi_hba *phba,
2777 struct mem_array *pmem, struct be_dma_mem *sgl)
2778{
2779 if (sgl->va)
2780 be_sgl_destroy_contiguous(sgl);
2781
2782 be_sgl_create_contiguous((unsigned char *)pmem->virtual_address,
2783 pmem->bus_address.u.a64.address,
2784 pmem->size, sgl);
2785}
2786
2787static int be_fill_queue(struct be_queue_info *q,
2788 u16 len, u16 entry_size, void *vaddress)
2789{
2790 struct be_dma_mem *mem = &q->dma_mem;
2791
2792 memset(q, 0, sizeof(*q));
2793 q->len = len;
2794 q->entry_size = entry_size;
2795 mem->size = len * entry_size;
2796 mem->va = vaddress;
2797 if (!mem->va)
2798 return -ENOMEM;
2799 memset(mem->va, 0, mem->size);
2800 return 0;
2801}
2802
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302803static int beiscsi_create_eqs(struct beiscsi_hba *phba,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302804 struct hwi_context_memory *phwi_context)
2805{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302806 unsigned int i, num_eq_pages;
John Soni Jose99bc5d52012-08-20 23:00:18 +05302807 int ret = 0, eq_for_mcc;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302808 struct be_queue_info *eq;
2809 struct be_dma_mem *mem;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302810 void *eq_vaddress;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302811 dma_addr_t paddr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302812
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302813 num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \
2814 sizeof(struct be_eq_entry));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302815
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302816 if (phba->msix_enabled)
2817 eq_for_mcc = 1;
2818 else
2819 eq_for_mcc = 0;
2820 for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
2821 eq = &phwi_context->be_eq[i].q;
2822 mem = &eq->dma_mem;
2823 phwi_context->be_eq[i].phba = phba;
2824 eq_vaddress = pci_alloc_consistent(phba->pcidev,
2825 num_eq_pages * PAGE_SIZE,
2826 &paddr);
2827 if (!eq_vaddress)
2828 goto create_eq_error;
2829
2830 mem->va = eq_vaddress;
2831 ret = be_fill_queue(eq, phba->params.num_eq_entries,
2832 sizeof(struct be_eq_entry), eq_vaddress);
2833 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302834 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2835 "BM_%d : be_fill_queue Failed for EQ\n");
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302836 goto create_eq_error;
2837 }
2838
2839 mem->dma = paddr;
2840 ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,
2841 phwi_context->cur_eqd);
2842 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302843 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2844 "BM_%d : beiscsi_cmd_eq_create"
2845 "Failed for EQ\n");
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302846 goto create_eq_error;
2847 }
John Soni Jose99bc5d52012-08-20 23:00:18 +05302848
2849 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2850 "BM_%d : eqid = %d\n",
2851 phwi_context->be_eq[i].q.id);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302852 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302853 return 0;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302854create_eq_error:
2855 for (i = 0; i < (phba->num_cpus + 1); i++) {
2856 eq = &phwi_context->be_eq[i].q;
2857 mem = &eq->dma_mem;
2858 if (mem->va)
2859 pci_free_consistent(phba->pcidev, num_eq_pages
2860 * PAGE_SIZE,
2861 mem->va, mem->dma);
2862 }
2863 return ret;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302864}
2865
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302866static int beiscsi_create_cqs(struct beiscsi_hba *phba,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302867 struct hwi_context_memory *phwi_context)
2868{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302869 unsigned int i, num_cq_pages;
John Soni Jose99bc5d52012-08-20 23:00:18 +05302870 int ret = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302871 struct be_queue_info *cq, *eq;
2872 struct be_dma_mem *mem;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302873 struct be_eq_obj *pbe_eq;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302874 void *cq_vaddress;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302875 dma_addr_t paddr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302876
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302877 num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
2878 sizeof(struct sol_cqe));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302879
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302880 for (i = 0; i < phba->num_cpus; i++) {
2881 cq = &phwi_context->be_cq[i];
2882 eq = &phwi_context->be_eq[i].q;
2883 pbe_eq = &phwi_context->be_eq[i];
2884 pbe_eq->cq = cq;
2885 pbe_eq->phba = phba;
2886 mem = &cq->dma_mem;
2887 cq_vaddress = pci_alloc_consistent(phba->pcidev,
2888 num_cq_pages * PAGE_SIZE,
2889 &paddr);
2890 if (!cq_vaddress)
2891 goto create_cq_error;
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05302892 ret = be_fill_queue(cq, phba->params.num_cq_entries,
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302893 sizeof(struct sol_cqe), cq_vaddress);
2894 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302895 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2896 "BM_%d : be_fill_queue Failed "
2897 "for ISCSI CQ\n");
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302898 goto create_cq_error;
2899 }
2900
2901 mem->dma = paddr;
2902 ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false,
2903 false, 0);
2904 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302905 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2906 "BM_%d : beiscsi_cmd_eq_create"
2907 "Failed for ISCSI CQ\n");
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302908 goto create_cq_error;
2909 }
John Soni Jose99bc5d52012-08-20 23:00:18 +05302910 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2911 "BM_%d : iscsi cq_id is %d for eq_id %d\n"
2912 "iSCSI CQ CREATED\n", cq->id, eq->id);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302913 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302914 return 0;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302915
2916create_cq_error:
2917 for (i = 0; i < phba->num_cpus; i++) {
2918 cq = &phwi_context->be_cq[i];
2919 mem = &cq->dma_mem;
2920 if (mem->va)
2921 pci_free_consistent(phba->pcidev, num_cq_pages
2922 * PAGE_SIZE,
2923 mem->va, mem->dma);
2924 }
2925 return ret;
2926
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302927}
2928
2929static int
2930beiscsi_create_def_hdr(struct beiscsi_hba *phba,
2931 struct hwi_context_memory *phwi_context,
2932 struct hwi_controller *phwi_ctrlr,
2933 unsigned int def_pdu_ring_sz)
2934{
2935 unsigned int idx;
2936 int ret;
2937 struct be_queue_info *dq, *cq;
2938 struct be_dma_mem *mem;
2939 struct be_mem_descriptor *mem_descr;
2940 void *dq_vaddress;
2941
2942 idx = 0;
2943 dq = &phwi_context->be_def_hdrq;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302944 cq = &phwi_context->be_cq[0];
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302945 mem = &dq->dma_mem;
2946 mem_descr = phba->init_mem;
2947 mem_descr += HWI_MEM_ASYNC_HEADER_RING;
2948 dq_vaddress = mem_descr->mem_array[idx].virtual_address;
2949 ret = be_fill_queue(dq, mem_descr->mem_array[0].size /
2950 sizeof(struct phys_addr),
2951 sizeof(struct phys_addr), dq_vaddress);
2952 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302953 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2954 "BM_%d : be_fill_queue Failed for DEF PDU HDR\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302955 return ret;
2956 }
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05302957 mem->dma = (unsigned long)mem_descr->mem_array[idx].
2958 bus_address.u.a64.address;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302959 ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq,
2960 def_pdu_ring_sz,
2961 phba->params.defpdu_hdr_sz);
2962 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05302963 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
2964 "BM_%d : be_cmd_create_default_pdu_queue Failed DEFHDR\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302965 return ret;
2966 }
2967 phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id;
John Soni Jose99bc5d52012-08-20 23:00:18 +05302968 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
2969 "BM_%d : iscsi def pdu id is %d\n",
2970 phwi_context->be_def_hdrq.id);
2971
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302972 hwi_post_async_buffers(phba, 1);
2973 return 0;
2974}
2975
2976static int
2977beiscsi_create_def_data(struct beiscsi_hba *phba,
2978 struct hwi_context_memory *phwi_context,
2979 struct hwi_controller *phwi_ctrlr,
2980 unsigned int def_pdu_ring_sz)
2981{
2982 unsigned int idx;
2983 int ret;
2984 struct be_queue_info *dataq, *cq;
2985 struct be_dma_mem *mem;
2986 struct be_mem_descriptor *mem_descr;
2987 void *dq_vaddress;
2988
2989 idx = 0;
2990 dataq = &phwi_context->be_def_dataq;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05302991 cq = &phwi_context->be_cq[0];
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05302992 mem = &dataq->dma_mem;
2993 mem_descr = phba->init_mem;
2994 mem_descr += HWI_MEM_ASYNC_DATA_RING;
2995 dq_vaddress = mem_descr->mem_array[idx].virtual_address;
2996 ret = be_fill_queue(dataq, mem_descr->mem_array[0].size /
2997 sizeof(struct phys_addr),
2998 sizeof(struct phys_addr), dq_vaddress);
2999 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303000 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3001 "BM_%d : be_fill_queue Failed for DEF PDU DATA\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303002 return ret;
3003 }
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05303004 mem->dma = (unsigned long)mem_descr->mem_array[idx].
3005 bus_address.u.a64.address;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303006 ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq,
3007 def_pdu_ring_sz,
3008 phba->params.defpdu_data_sz);
3009 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303010 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3011 "BM_%d be_cmd_create_default_pdu_queue"
3012 " Failed for DEF PDU DATA\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303013 return ret;
3014 }
3015 phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303016 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3017 "BM_%d : iscsi def data id is %d\n",
3018 phwi_context->be_def_dataq.id);
3019
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303020 hwi_post_async_buffers(phba, 0);
John Soni Jose99bc5d52012-08-20 23:00:18 +05303021 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3022 "BM_%d : DEFAULT PDU DATA RING CREATED\n");
3023
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303024 return 0;
3025}
3026
3027static int
3028beiscsi_post_pages(struct beiscsi_hba *phba)
3029{
3030 struct be_mem_descriptor *mem_descr;
3031 struct mem_array *pm_arr;
3032 unsigned int page_offset, i;
3033 struct be_dma_mem sgl;
3034 int status;
3035
3036 mem_descr = phba->init_mem;
3037 mem_descr += HWI_MEM_SGE;
3038 pm_arr = mem_descr->mem_array;
3039
3040 page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io *
3041 phba->fw_config.iscsi_icd_start) / PAGE_SIZE;
3042 for (i = 0; i < mem_descr->num_elements; i++) {
3043 hwi_build_be_sgl_arr(phba, pm_arr, &sgl);
3044 status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl,
3045 page_offset,
3046 (pm_arr->size / PAGE_SIZE));
3047 page_offset += pm_arr->size / PAGE_SIZE;
3048 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303049 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3050 "BM_%d : post sgl failed.\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303051 return status;
3052 }
3053 pm_arr++;
3054 }
John Soni Jose99bc5d52012-08-20 23:00:18 +05303055 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3056 "BM_%d : POSTED PAGES\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303057 return 0;
3058}
3059
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303060static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q)
3061{
3062 struct be_dma_mem *mem = &q->dma_mem;
Jayamohan Kallickalc8b25592012-04-03 23:41:42 -05003063 if (mem->va) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303064 pci_free_consistent(phba->pcidev, mem->size,
3065 mem->va, mem->dma);
Jayamohan Kallickalc8b25592012-04-03 23:41:42 -05003066 mem->va = NULL;
3067 }
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303068}
3069
3070static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
3071 u16 len, u16 entry_size)
3072{
3073 struct be_dma_mem *mem = &q->dma_mem;
3074
3075 memset(q, 0, sizeof(*q));
3076 q->len = len;
3077 q->entry_size = entry_size;
3078 mem->size = len * entry_size;
3079 mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma);
3080 if (!mem->va)
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +05303081 return -ENOMEM;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303082 memset(mem->va, 0, mem->size);
3083 return 0;
3084}
3085
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303086static int
3087beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
3088 struct hwi_context_memory *phwi_context,
3089 struct hwi_controller *phwi_ctrlr)
3090{
3091 unsigned int wrb_mem_index, offset, size, num_wrb_rings;
3092 u64 pa_addr_lo;
3093 unsigned int idx, num, i;
3094 struct mem_array *pwrb_arr;
3095 void *wrb_vaddr;
3096 struct be_dma_mem sgl;
3097 struct be_mem_descriptor *mem_descr;
3098 int status;
3099
3100 idx = 0;
3101 mem_descr = phba->init_mem;
3102 mem_descr += HWI_MEM_WRB;
3103 pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl,
3104 GFP_KERNEL);
3105 if (!pwrb_arr) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303106 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3107 "BM_%d : Memory alloc failed in create wrb ring.\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303108 return -ENOMEM;
3109 }
3110 wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
3111 pa_addr_lo = mem_descr->mem_array[idx].bus_address.u.a64.address;
3112 num_wrb_rings = mem_descr->mem_array[idx].size /
3113 (phba->params.wrbs_per_cxn * sizeof(struct iscsi_wrb));
3114
3115 for (num = 0; num < phba->params.cxns_per_ctrl; num++) {
3116 if (num_wrb_rings) {
3117 pwrb_arr[num].virtual_address = wrb_vaddr;
3118 pwrb_arr[num].bus_address.u.a64.address = pa_addr_lo;
3119 pwrb_arr[num].size = phba->params.wrbs_per_cxn *
3120 sizeof(struct iscsi_wrb);
3121 wrb_vaddr += pwrb_arr[num].size;
3122 pa_addr_lo += pwrb_arr[num].size;
3123 num_wrb_rings--;
3124 } else {
3125 idx++;
3126 wrb_vaddr = mem_descr->mem_array[idx].virtual_address;
3127 pa_addr_lo = mem_descr->mem_array[idx].\
3128 bus_address.u.a64.address;
3129 num_wrb_rings = mem_descr->mem_array[idx].size /
3130 (phba->params.wrbs_per_cxn *
3131 sizeof(struct iscsi_wrb));
3132 pwrb_arr[num].virtual_address = wrb_vaddr;
3133 pwrb_arr[num].bus_address.u.a64.address\
3134 = pa_addr_lo;
3135 pwrb_arr[num].size = phba->params.wrbs_per_cxn *
3136 sizeof(struct iscsi_wrb);
3137 wrb_vaddr += pwrb_arr[num].size;
3138 pa_addr_lo += pwrb_arr[num].size;
3139 num_wrb_rings--;
3140 }
3141 }
3142 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
3143 wrb_mem_index = 0;
3144 offset = 0;
3145 size = 0;
3146
3147 hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl);
3148 status = be_cmd_wrbq_create(&phba->ctrl, &sgl,
3149 &phwi_context->be_wrbq[i]);
3150 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303151 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3152 "BM_%d : wrbq create failed.");
Dan Carpenter1462b8f2010-06-10 09:52:21 +02003153 kfree(pwrb_arr);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303154 return status;
3155 }
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05303156 phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i].
3157 id;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303158 }
3159 kfree(pwrb_arr);
3160 return 0;
3161}
3162
3163static void free_wrb_handles(struct beiscsi_hba *phba)
3164{
3165 unsigned int index;
3166 struct hwi_controller *phwi_ctrlr;
3167 struct hwi_wrb_context *pwrb_context;
3168
3169 phwi_ctrlr = phba->phwi_ctrlr;
3170 for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) {
3171 pwrb_context = &phwi_ctrlr->wrb_context[index];
3172 kfree(pwrb_context->pwrb_handle_base);
3173 kfree(pwrb_context->pwrb_handle_basestd);
3174 }
3175}
3176
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303177static void be_mcc_queues_destroy(struct beiscsi_hba *phba)
3178{
3179 struct be_queue_info *q;
3180 struct be_ctrl_info *ctrl = &phba->ctrl;
3181
3182 q = &phba->ctrl.mcc_obj.q;
3183 if (q->created)
3184 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
3185 be_queue_free(phba, q);
3186
3187 q = &phba->ctrl.mcc_obj.cq;
3188 if (q->created)
3189 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
3190 be_queue_free(phba, q);
3191}
3192
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303193static void hwi_cleanup(struct beiscsi_hba *phba)
3194{
3195 struct be_queue_info *q;
3196 struct be_ctrl_info *ctrl = &phba->ctrl;
3197 struct hwi_controller *phwi_ctrlr;
3198 struct hwi_context_memory *phwi_context;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303199 int i, eq_num;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303200
3201 phwi_ctrlr = phba->phwi_ctrlr;
3202 phwi_context = phwi_ctrlr->phwi_ctxt;
3203 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
3204 q = &phwi_context->be_wrbq[i];
3205 if (q->created)
3206 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);
3207 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303208 free_wrb_handles(phba);
3209
3210 q = &phwi_context->be_def_hdrq;
3211 if (q->created)
3212 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
3213
3214 q = &phwi_context->be_def_dataq;
3215 if (q->created)
3216 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
3217
3218 beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL);
3219
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303220 for (i = 0; i < (phba->num_cpus); i++) {
3221 q = &phwi_context->be_cq[i];
3222 if (q->created)
3223 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);
3224 }
3225 if (phba->msix_enabled)
3226 eq_num = 1;
3227 else
3228 eq_num = 0;
3229 for (i = 0; i < (phba->num_cpus + eq_num); i++) {
3230 q = &phwi_context->be_eq[i].q;
3231 if (q->created)
3232 beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
3233 }
3234 be_mcc_queues_destroy(phba);
3235}
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303236
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303237static int be_mcc_queues_create(struct beiscsi_hba *phba,
3238 struct hwi_context_memory *phwi_context)
3239{
3240 struct be_queue_info *q, *cq;
3241 struct be_ctrl_info *ctrl = &phba->ctrl;
3242
3243 /* Alloc MCC compl queue */
3244 cq = &phba->ctrl.mcc_obj.cq;
3245 if (be_queue_alloc(phba, cq, MCC_CQ_LEN,
3246 sizeof(struct be_mcc_compl)))
3247 goto err;
3248 /* Ask BE to create MCC compl queue; */
3249 if (phba->msix_enabled) {
3250 if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq
3251 [phba->num_cpus].q, false, true, 0))
3252 goto mcc_cq_free;
3253 } else {
3254 if (beiscsi_cmd_cq_create(ctrl, cq, &phwi_context->be_eq[0].q,
3255 false, true, 0))
3256 goto mcc_cq_free;
3257 }
3258
3259 /* Alloc MCC queue */
3260 q = &phba->ctrl.mcc_obj.q;
3261 if (be_queue_alloc(phba, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
3262 goto mcc_cq_destroy;
3263
3264 /* Ask BE to create MCC queue */
Jayamohan Kallickal35e66012009-10-23 11:53:49 +05303265 if (beiscsi_cmd_mccq_create(phba, q, cq))
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303266 goto mcc_q_free;
3267
3268 return 0;
3269
3270mcc_q_free:
3271 be_queue_free(phba, q);
3272mcc_cq_destroy:
3273 beiscsi_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
3274mcc_cq_free:
3275 be_queue_free(phba, cq);
3276err:
Jayamohan Kallickald3ad2bb2010-07-22 04:16:38 +05303277 return -ENOMEM;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303278}
3279
3280static int find_num_cpus(void)
3281{
3282 int num_cpus = 0;
3283
3284 num_cpus = num_online_cpus();
3285 if (num_cpus >= MAX_CPUS)
3286 num_cpus = MAX_CPUS - 1;
3287
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303288 return num_cpus;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303289}
3290
3291static int hwi_init_port(struct beiscsi_hba *phba)
3292{
3293 struct hwi_controller *phwi_ctrlr;
3294 struct hwi_context_memory *phwi_context;
3295 unsigned int def_pdu_ring_sz;
3296 struct be_ctrl_info *ctrl = &phba->ctrl;
3297 int status;
3298
3299 def_pdu_ring_sz =
3300 phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr);
3301 phwi_ctrlr = phba->phwi_ctrlr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303302 phwi_context = phwi_ctrlr->phwi_ctxt;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303303 phwi_context->max_eqd = 0;
3304 phwi_context->min_eqd = 0;
3305 phwi_context->cur_eqd = 64;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303306 be_cmd_fw_initialize(&phba->ctrl);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303307
3308 status = beiscsi_create_eqs(phba, phwi_context);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303309 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303310 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3311 "BM_%d : EQ not created\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303312 goto error;
3313 }
3314
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303315 status = be_mcc_queues_create(phba, phwi_context);
3316 if (status != 0)
3317 goto error;
3318
3319 status = mgmt_check_supported_fw(ctrl, phba);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303320 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303321 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3322 "BM_%d : Unsupported fw version\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303323 goto error;
3324 }
3325
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303326 status = beiscsi_create_cqs(phba, phwi_context);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303327 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303328 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3329 "BM_%d : CQ not created\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303330 goto error;
3331 }
3332
3333 status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr,
3334 def_pdu_ring_sz);
3335 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303336 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3337 "BM_%d : Default Header not created\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303338 goto error;
3339 }
3340
3341 status = beiscsi_create_def_data(phba, phwi_context,
3342 phwi_ctrlr, def_pdu_ring_sz);
3343 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303344 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3345 "BM_%d : Default Data not created\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303346 goto error;
3347 }
3348
3349 status = beiscsi_post_pages(phba);
3350 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303351 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3352 "BM_%d : Post SGL Pages Failed\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303353 goto error;
3354 }
3355
3356 status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr);
3357 if (status != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303358 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3359 "BM_%d : WRB Rings not created\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303360 goto error;
3361 }
3362
John Soni Jose99bc5d52012-08-20 23:00:18 +05303363 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3364 "BM_%d : hwi_init_port success\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303365 return 0;
3366
3367error:
John Soni Jose99bc5d52012-08-20 23:00:18 +05303368 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3369 "BM_%d : hwi_init_port failed");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303370 hwi_cleanup(phba);
Jayamohan Kallickala49e06d2012-04-03 23:41:44 -05003371 return status;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303372}
3373
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303374static int hwi_init_controller(struct beiscsi_hba *phba)
3375{
3376 struct hwi_controller *phwi_ctrlr;
3377
3378 phwi_ctrlr = phba->phwi_ctrlr;
3379 if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) {
3380 phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba->
3381 init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303382 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3383 "BM_%d : phwi_ctrlr->phwi_ctxt=%p\n",
3384 phwi_ctrlr->phwi_ctxt);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303385 } else {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303386 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3387 "BM_%d : HWI_MEM_ADDN_CONTEXT is more "
3388 "than one element.Failing to load\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303389 return -ENOMEM;
3390 }
3391
3392 iscsi_init_global_templates(phba);
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05003393 if (beiscsi_init_wrb_handle(phba))
3394 return -ENOMEM;
3395
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303396 hwi_init_async_pdu_ctx(phba);
3397 if (hwi_init_port(phba) != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303398 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3399 "BM_%d : hwi_init_controller failed\n");
3400
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303401 return -ENOMEM;
3402 }
3403 return 0;
3404}
3405
3406static void beiscsi_free_mem(struct beiscsi_hba *phba)
3407{
3408 struct be_mem_descriptor *mem_descr;
3409 int i, j;
3410
3411 mem_descr = phba->init_mem;
3412 i = 0;
3413 j = 0;
3414 for (i = 0; i < SE_MEM_MAX; i++) {
3415 for (j = mem_descr->num_elements; j > 0; j--) {
3416 pci_free_consistent(phba->pcidev,
3417 mem_descr->mem_array[j - 1].size,
3418 mem_descr->mem_array[j - 1].virtual_address,
Jayamohan Kallickal457ff3b2010-07-22 04:16:00 +05303419 (unsigned long)mem_descr->mem_array[j - 1].
3420 bus_address.u.a64.address);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303421 }
3422 kfree(mem_descr->mem_array);
3423 mem_descr++;
3424 }
3425 kfree(phba->init_mem);
3426 kfree(phba->phwi_ctrlr);
3427}
3428
3429static int beiscsi_init_controller(struct beiscsi_hba *phba)
3430{
3431 int ret = -ENOMEM;
3432
3433 ret = beiscsi_get_memory(phba);
3434 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303435 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3436 "BM_%d : beiscsi_dev_probe -"
3437 "Failed in beiscsi_alloc_memory\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303438 return ret;
3439 }
3440
3441 ret = hwi_init_controller(phba);
3442 if (ret)
3443 goto free_init;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303444 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3445 "BM_%d : Return success from beiscsi_init_controller");
3446
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303447 return 0;
3448
3449free_init:
3450 beiscsi_free_mem(phba);
Jayamohan Kallickala49e06d2012-04-03 23:41:44 -05003451 return ret;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303452}
3453
3454static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
3455{
3456 struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg;
3457 struct sgl_handle *psgl_handle;
3458 struct iscsi_sge *pfrag;
3459 unsigned int arr_index, i, idx;
3460
3461 phba->io_sgl_hndl_avbl = 0;
3462 phba->eh_sgl_hndl_avbl = 0;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303463
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303464 mem_descr_sglh = phba->init_mem;
3465 mem_descr_sglh += HWI_MEM_SGLH;
3466 if (1 == mem_descr_sglh->num_elements) {
3467 phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
3468 phba->params.ios_per_ctrl,
3469 GFP_KERNEL);
3470 if (!phba->io_sgl_hndl_base) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303471 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3472 "BM_%d : Mem Alloc Failed. Failing to load\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303473 return -ENOMEM;
3474 }
3475 phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
3476 (phba->params.icds_per_ctrl -
3477 phba->params.ios_per_ctrl),
3478 GFP_KERNEL);
3479 if (!phba->eh_sgl_hndl_base) {
3480 kfree(phba->io_sgl_hndl_base);
John Soni Jose99bc5d52012-08-20 23:00:18 +05303481 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3482 "BM_%d : Mem Alloc Failed. Failing to load\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303483 return -ENOMEM;
3484 }
3485 } else {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303486 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3487 "BM_%d : HWI_MEM_SGLH is more than one element."
3488 "Failing to load\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303489 return -ENOMEM;
3490 }
3491
3492 arr_index = 0;
3493 idx = 0;
3494 while (idx < mem_descr_sglh->num_elements) {
3495 psgl_handle = mem_descr_sglh->mem_array[idx].virtual_address;
3496
3497 for (i = 0; i < (mem_descr_sglh->mem_array[idx].size /
3498 sizeof(struct sgl_handle)); i++) {
3499 if (arr_index < phba->params.ios_per_ctrl) {
3500 phba->io_sgl_hndl_base[arr_index] = psgl_handle;
3501 phba->io_sgl_hndl_avbl++;
3502 arr_index++;
3503 } else {
3504 phba->eh_sgl_hndl_base[arr_index -
3505 phba->params.ios_per_ctrl] =
3506 psgl_handle;
3507 arr_index++;
3508 phba->eh_sgl_hndl_avbl++;
3509 }
3510 psgl_handle++;
3511 }
3512 idx++;
3513 }
John Soni Jose99bc5d52012-08-20 23:00:18 +05303514 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3515 "BM_%d : phba->io_sgl_hndl_avbl=%d"
3516 "phba->eh_sgl_hndl_avbl=%d\n",
3517 phba->io_sgl_hndl_avbl,
3518 phba->eh_sgl_hndl_avbl);
3519
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303520 mem_descr_sg = phba->init_mem;
3521 mem_descr_sg += HWI_MEM_SGE;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303522 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3523 "\n BM_%d : mem_descr_sg->num_elements=%d\n",
3524 mem_descr_sg->num_elements);
3525
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303526 arr_index = 0;
3527 idx = 0;
3528 while (idx < mem_descr_sg->num_elements) {
3529 pfrag = mem_descr_sg->mem_array[idx].virtual_address;
3530
3531 for (i = 0;
3532 i < (mem_descr_sg->mem_array[idx].size) /
3533 (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io);
3534 i++) {
3535 if (arr_index < phba->params.ios_per_ctrl)
3536 psgl_handle = phba->io_sgl_hndl_base[arr_index];
3537 else
3538 psgl_handle = phba->eh_sgl_hndl_base[arr_index -
3539 phba->params.ios_per_ctrl];
3540 psgl_handle->pfrag = pfrag;
3541 AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0);
3542 AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0);
3543 pfrag += phba->params.num_sge_per_io;
3544 psgl_handle->sgl_index =
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05303545 phba->fw_config.iscsi_icd_start + arr_index++;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303546 }
3547 idx++;
3548 }
3549 phba->io_sgl_free_index = 0;
3550 phba->io_sgl_alloc_index = 0;
3551 phba->eh_sgl_free_index = 0;
3552 phba->eh_sgl_alloc_index = 0;
3553 return 0;
3554}
3555
3556static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
3557{
3558 int i, new_cid;
3559
Jayamohan Kallickalc2462282010-01-05 05:05:34 +05303560 phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303561 GFP_KERNEL);
3562 if (!phba->cid_array) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303563 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3564 "BM_%d : Failed to allocate memory in "
3565 "hba_setup_cid_tbls\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303566 return -ENOMEM;
3567 }
Jayamohan Kallickalc2462282010-01-05 05:05:34 +05303568 phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) *
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303569 phba->params.cxns_per_ctrl * 2, GFP_KERNEL);
3570 if (!phba->ep_array) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303571 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3572 "BM_%d : Failed to allocate memory in "
3573 "hba_setup_cid_tbls\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303574 kfree(phba->cid_array);
3575 return -ENOMEM;
3576 }
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05303577 new_cid = phba->fw_config.iscsi_cid_start;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303578 for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
3579 phba->cid_array[i] = new_cid;
3580 new_cid += 2;
3581 }
3582 phba->avlbl_cids = phba->params.cxns_per_ctrl;
3583 return 0;
3584}
3585
Jayamohan Kallickal238f6b72010-07-22 04:23:22 +05303586static void hwi_enable_intr(struct beiscsi_hba *phba)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303587{
3588 struct be_ctrl_info *ctrl = &phba->ctrl;
3589 struct hwi_controller *phwi_ctrlr;
3590 struct hwi_context_memory *phwi_context;
3591 struct be_queue_info *eq;
3592 u8 __iomem *addr;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303593 u32 reg, i;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303594 u32 enabled;
3595
3596 phwi_ctrlr = phba->phwi_ctrlr;
3597 phwi_context = phwi_ctrlr->phwi_ctxt;
3598
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303599 addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
3600 PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
3601 reg = ioread32(addr);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303602
3603 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
3604 if (!enabled) {
3605 reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303606 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3607 "BM_%d : reg =x%08x addr=%p\n", reg, addr);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303608 iowrite32(reg, addr);
Jayamohan Kallickal665d6d92011-04-29 14:30:06 -05003609 }
3610
3611 if (!phba->msix_enabled) {
3612 eq = &phwi_context->be_eq[0].q;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303613 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3614 "BM_%d : eq->id=%d\n", eq->id);
3615
Jayamohan Kallickal665d6d92011-04-29 14:30:06 -05003616 hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
3617 } else {
3618 for (i = 0; i <= phba->num_cpus; i++) {
3619 eq = &phwi_context->be_eq[i].q;
John Soni Jose99bc5d52012-08-20 23:00:18 +05303620 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
3621 "BM_%d : eq->id=%d\n", eq->id);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303622 hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
3623 }
Jayamohan Kallickalc03af1a2010-02-20 08:05:43 +05303624 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303625}
3626
3627static void hwi_disable_intr(struct beiscsi_hba *phba)
3628{
3629 struct be_ctrl_info *ctrl = &phba->ctrl;
3630
3631 u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
3632 u32 reg = ioread32(addr);
3633
3634 u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
3635 if (enabled) {
3636 reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
3637 iowrite32(reg, addr);
3638 } else
John Soni Jose99bc5d52012-08-20 23:00:18 +05303639 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
3640 "BM_%d : In hwi_disable_intr, Already Disabled\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303641}
3642
John Soni Jose9aef4202012-08-20 23:00:08 +05303643/**
3644 * beiscsi_get_boot_info()- Get the boot session info
3645 * @phba: The device priv structure instance
3646 *
3647 * Get the boot target info and store in driver priv structure
3648 *
3649 * return values
3650 * Success: 0
3651 * Failure: Non-Zero Value
3652 **/
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303653static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
3654{
Mike Christie0e438952012-04-03 23:41:51 -05003655 struct be_cmd_get_session_resp *session_resp;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303656 struct be_mcc_wrb *wrb;
3657 struct be_dma_mem nonemb_cmd;
3658 unsigned int tag, wrb_num;
3659 unsigned short status, extd_status;
John Soni Jose9aef4202012-08-20 23:00:08 +05303660 unsigned int s_handle;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303661 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
Mike Christief457a462011-06-24 15:11:53 -05003662 int ret = -ENOMEM;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303663
John Soni Jose9aef4202012-08-20 23:00:08 +05303664 /* Get the session handle of the boot target */
3665 ret = be_mgmt_get_boot_shandle(phba, &s_handle);
3666 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303667 beiscsi_log(phba, KERN_ERR,
3668 BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
3669 "BM_%d : No boot session\n");
John Soni Jose9aef4202012-08-20 23:00:08 +05303670 return ret;
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303671 }
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303672 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
3673 sizeof(*session_resp),
3674 &nonemb_cmd.dma);
3675 if (nonemb_cmd.va == NULL) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303676 beiscsi_log(phba, KERN_ERR,
3677 BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
3678 "BM_%d : Failed to allocate memory for"
3679 "beiscsi_get_session_info\n");
3680
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303681 return -ENOMEM;
3682 }
3683
3684 memset(nonemb_cmd.va, 0, sizeof(*session_resp));
John Soni Jose9aef4202012-08-20 23:00:08 +05303685 tag = mgmt_get_session_info(phba, s_handle,
Mike Christie0e438952012-04-03 23:41:51 -05003686 &nonemb_cmd);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303687 if (!tag) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303688 beiscsi_log(phba, KERN_ERR,
3689 BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
3690 "BM_%d : beiscsi_get_session_info"
3691 " Failed\n");
3692
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303693 goto boot_freemem;
3694 } else
3695 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
3696 phba->ctrl.mcc_numtag[tag]);
3697
3698 wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
3699 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
3700 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
3701 if (status || extd_status) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303702 beiscsi_log(phba, KERN_ERR,
3703 BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
3704 "BM_%d : beiscsi_get_session_info Failed"
3705 " status = %d extd_status = %d\n",
3706 status, extd_status);
3707
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303708 free_mcc_tag(&phba->ctrl, tag);
3709 goto boot_freemem;
3710 }
3711 wrb = queue_get_wrb(mccq, wrb_num);
3712 free_mcc_tag(&phba->ctrl, tag);
3713 session_resp = nonemb_cmd.va ;
Mike Christief457a462011-06-24 15:11:53 -05003714
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303715 memcpy(&phba->boot_sess, &session_resp->session_info,
3716 sizeof(struct mgmt_session_info));
Mike Christief457a462011-06-24 15:11:53 -05003717 ret = 0;
3718
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303719boot_freemem:
3720 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
3721 nonemb_cmd.va, nonemb_cmd.dma);
Mike Christief457a462011-06-24 15:11:53 -05003722 return ret;
3723}
3724
3725static void beiscsi_boot_release(void *data)
3726{
3727 struct beiscsi_hba *phba = data;
3728
3729 scsi_host_put(phba->shost);
3730}
3731
3732static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
3733{
3734 struct iscsi_boot_kobj *boot_kobj;
3735
3736 /* get boot info using mgmt cmd */
3737 if (beiscsi_get_boot_info(phba))
3738 /* Try to see if we can carry on without this */
3739 return 0;
3740
3741 phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
3742 if (!phba->boot_kset)
3743 return -ENOMEM;
3744
3745 /* get a ref because the show function will ref the phba */
3746 if (!scsi_host_get(phba->shost))
3747 goto free_kset;
3748 boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
3749 beiscsi_show_boot_tgt_info,
3750 beiscsi_tgt_get_attr_visibility,
3751 beiscsi_boot_release);
3752 if (!boot_kobj)
3753 goto put_shost;
3754
3755 if (!scsi_host_get(phba->shost))
3756 goto free_kset;
3757 boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
3758 beiscsi_show_boot_ini_info,
3759 beiscsi_ini_get_attr_visibility,
3760 beiscsi_boot_release);
3761 if (!boot_kobj)
3762 goto put_shost;
3763
3764 if (!scsi_host_get(phba->shost))
3765 goto free_kset;
3766 boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
3767 beiscsi_show_boot_eth_info,
3768 beiscsi_eth_get_attr_visibility,
3769 beiscsi_boot_release);
3770 if (!boot_kobj)
3771 goto put_shost;
3772 return 0;
3773
3774put_shost:
3775 scsi_host_put(phba->shost);
3776free_kset:
3777 iscsi_boot_destroy_kset(phba->boot_kset);
Jayamohan Kallickalc7acc5b2010-07-22 04:29:18 +05303778 return -ENOMEM;
3779}
3780
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303781static int beiscsi_init_port(struct beiscsi_hba *phba)
3782{
3783 int ret;
3784
3785 ret = beiscsi_init_controller(phba);
3786 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303787 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3788 "BM_%d : beiscsi_dev_probe - Failed in"
3789 "beiscsi_init_controller\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303790 return ret;
3791 }
3792 ret = beiscsi_init_sgl_handle(phba);
3793 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303794 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3795 "BM_%d : beiscsi_dev_probe - Failed in"
3796 "beiscsi_init_sgl_handle\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303797 goto do_cleanup_ctrlr;
3798 }
3799
3800 if (hba_setup_cid_tbls(phba)) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05303801 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
3802 "BM_%d : Failed in hba_setup_cid_tbls\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303803 kfree(phba->io_sgl_hndl_base);
3804 kfree(phba->eh_sgl_hndl_base);
3805 goto do_cleanup_ctrlr;
3806 }
3807
3808 return ret;
3809
3810do_cleanup_ctrlr:
3811 hwi_cleanup(phba);
3812 return ret;
3813}
3814
3815static void hwi_purge_eq(struct beiscsi_hba *phba)
3816{
3817 struct hwi_controller *phwi_ctrlr;
3818 struct hwi_context_memory *phwi_context;
3819 struct be_queue_info *eq;
3820 struct be_eq_entry *eqe = NULL;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303821 int i, eq_msix;
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303822 unsigned int num_processed;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303823
3824 phwi_ctrlr = phba->phwi_ctrlr;
3825 phwi_context = phwi_ctrlr->phwi_ctxt;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303826 if (phba->msix_enabled)
3827 eq_msix = 1;
3828 else
3829 eq_msix = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303830
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303831 for (i = 0; i < (phba->num_cpus + eq_msix); i++) {
3832 eq = &phwi_context->be_eq[i].q;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303833 eqe = queue_tail_node(eq);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303834 num_processed = 0;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303835 while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
3836 & EQE_VALID_MASK) {
3837 AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
3838 queue_tail_inc(eq);
3839 eqe = queue_tail_node(eq);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303840 num_processed++;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05303841 }
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303842
3843 if (num_processed)
3844 hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303845 }
3846}
3847
3848static void beiscsi_clean_port(struct beiscsi_hba *phba)
3849{
Jayamohan Kallickal03a12312010-07-22 04:17:16 +05303850 int mgmt_status;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303851
3852 mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0);
3853 if (mgmt_status)
John Soni Jose99bc5d52012-08-20 23:00:18 +05303854 beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
3855 "BM_%d : mgmt_epfw_cleanup FAILED\n");
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303856
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303857 hwi_purge_eq(phba);
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05303858 hwi_cleanup(phba);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303859 kfree(phba->io_sgl_hndl_base);
3860 kfree(phba->eh_sgl_hndl_base);
3861 kfree(phba->cid_array);
3862 kfree(phba->ep_array);
3863}
3864
Mike Christie1282ab72012-04-18 03:06:00 -05003865static void beiscsi_cleanup_task(struct iscsi_task *task)
3866{
3867 struct beiscsi_io_task *io_task = task->dd_data;
3868 struct iscsi_conn *conn = task->conn;
3869 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
3870 struct beiscsi_hba *phba = beiscsi_conn->phba;
3871 struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
3872 struct hwi_wrb_context *pwrb_context;
3873 struct hwi_controller *phwi_ctrlr;
3874
3875 phwi_ctrlr = phba->phwi_ctrlr;
3876 pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid
3877 - phba->fw_config.iscsi_cid_start];
3878
3879 if (io_task->cmd_bhs) {
3880 pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
3881 io_task->bhs_pa.u.a64.address);
3882 io_task->cmd_bhs = NULL;
3883 }
3884
3885 if (task->sc) {
3886 if (io_task->pwrb_handle) {
3887 free_wrb_handle(phba, pwrb_context,
3888 io_task->pwrb_handle);
3889 io_task->pwrb_handle = NULL;
3890 }
3891
3892 if (io_task->psgl_handle) {
3893 spin_lock(&phba->io_sgl_lock);
3894 free_io_sgl_handle(phba, io_task->psgl_handle);
3895 spin_unlock(&phba->io_sgl_lock);
3896 io_task->psgl_handle = NULL;
3897 }
3898 } else {
3899 if (!beiscsi_conn->login_in_progress) {
3900 if (io_task->pwrb_handle) {
3901 free_wrb_handle(phba, pwrb_context,
3902 io_task->pwrb_handle);
3903 io_task->pwrb_handle = NULL;
3904 }
3905 if (io_task->psgl_handle) {
3906 spin_lock(&phba->mgmt_sgl_lock);
3907 free_mgmt_sgl_handle(phba,
3908 io_task->psgl_handle);
3909 spin_unlock(&phba->mgmt_sgl_lock);
3910 io_task->psgl_handle = NULL;
3911 }
3912 }
3913 }
3914}
3915
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303916void
3917beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
3918 struct beiscsi_offload_params *params)
3919{
3920 struct wrb_handle *pwrb_handle;
3921 struct iscsi_target_context_update_wrb *pwrb = NULL;
3922 struct be_mem_descriptor *mem_descr;
3923 struct beiscsi_hba *phba = beiscsi_conn->phba;
Mike Christie1282ab72012-04-18 03:06:00 -05003924 struct iscsi_task *task = beiscsi_conn->task;
3925 struct iscsi_session *session = task->conn->session;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303926 u32 doorbell = 0;
3927
3928 /*
3929 * We can always use 0 here because it is reserved by libiscsi for
3930 * login/startup related tasks.
3931 */
Mike Christie1282ab72012-04-18 03:06:00 -05003932 beiscsi_conn->login_in_progress = 0;
3933 spin_lock_bh(&session->lock);
3934 beiscsi_cleanup_task(task);
3935 spin_unlock_bh(&session->lock);
3936
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05303937 pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid -
Jayamohan Kallickald5431482010-01-05 05:06:21 +05303938 phba->fw_config.iscsi_cid_start));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05303939 pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb;
3940 memset(pwrb, 0, sizeof(*pwrb));
3941 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3942 max_burst_length, pwrb, params->dw[offsetof
3943 (struct amap_beiscsi_offload_params,
3944 max_burst_length) / 32]);
3945 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3946 max_send_data_segment_length, pwrb,
3947 params->dw[offsetof(struct amap_beiscsi_offload_params,
3948 max_send_data_segment_length) / 32]);
3949 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3950 first_burst_length,
3951 pwrb,
3952 params->dw[offsetof(struct amap_beiscsi_offload_params,
3953 first_burst_length) / 32]);
3954
3955 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb,
3956 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3957 erl) / 32] & OFFLD_PARAMS_ERL));
3958 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb,
3959 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3960 dde) / 32] & OFFLD_PARAMS_DDE) >> 2);
3961 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb,
3962 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3963 hde) / 32] & OFFLD_PARAMS_HDE) >> 3);
3964 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb,
3965 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3966 ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4);
3967 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb,
3968 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3969 imd) / 32] & OFFLD_PARAMS_IMD) >> 5);
3970 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn,
3971 pwrb,
3972 (params->dw[offsetof(struct amap_beiscsi_offload_params,
3973 exp_statsn) / 32] + 1));
3974 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb,
3975 0x7);
3976 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx,
3977 pwrb, pwrb_handle->wrb_index);
3978 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
3979 pwrb, pwrb_handle->nxt_wrb_index);
3980 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3981 session_state, pwrb, 0);
3982 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack,
3983 pwrb, 1);
3984 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq,
3985 pwrb, 0);
3986 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb,
3987 0);
3988
3989 mem_descr = phba->init_mem;
3990 mem_descr += ISCSI_MEM_GLOBAL_HEADER;
3991
3992 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3993 pad_buffer_addr_hi, pwrb,
3994 mem_descr->mem_array[0].bus_address.u.a32.address_hi);
3995 AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
3996 pad_buffer_addr_lo, pwrb,
3997 mem_descr->mem_array[0].bus_address.u.a32.address_lo);
3998
3999 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb));
4000
4001 doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304002 doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK)
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304003 << DB_DEF_PDU_WRB_INDEX_SHIFT;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304004 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
4005
4006 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
4007}
4008
4009static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
4010 int *index, int *age)
4011{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304012 *index = (int)itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304013 if (age)
4014 *age = conn->session->age;
4015}
4016
4017/**
4018 * beiscsi_alloc_pdu - allocates pdu and related resources
4019 * @task: libiscsi task
4020 * @opcode: opcode of pdu for task
4021 *
4022 * This is called with the session lock held. It will allocate
4023 * the wrb and sgl if needed for the command. And it will prep
4024 * the pdu's itt. beiscsi_parse_pdu will later translate
4025 * the pdu itt to the libiscsi task itt.
4026 */
4027static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
4028{
4029 struct beiscsi_io_task *io_task = task->dd_data;
4030 struct iscsi_conn *conn = task->conn;
4031 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
4032 struct beiscsi_hba *phba = beiscsi_conn->phba;
4033 struct hwi_wrb_context *pwrb_context;
4034 struct hwi_controller *phwi_ctrlr;
4035 itt_t itt;
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304036 struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;
4037 dma_addr_t paddr;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304038
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304039 io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool,
Mike Christiebc7acce2010-12-31 02:22:19 -06004040 GFP_ATOMIC, &paddr);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304041 if (!io_task->cmd_bhs)
4042 return -ENOMEM;
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304043 io_task->bhs_pa.u.a64.address = paddr;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304044 io_task->libiscsi_itt = (itt_t)task->itt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304045 io_task->conn = beiscsi_conn;
4046
4047 task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
4048 task->hdr_max = sizeof(struct be_cmd_bhs);
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304049 io_task->psgl_handle = NULL;
Jayamohan Kallickal3ec78272012-04-03 23:41:38 -05004050 io_task->pwrb_handle = NULL;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304051
4052 if (task->sc) {
4053 spin_lock(&phba->io_sgl_lock);
4054 io_task->psgl_handle = alloc_io_sgl_handle(phba);
4055 spin_unlock(&phba->io_sgl_lock);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304056 if (!io_task->psgl_handle)
4057 goto free_hndls;
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304058 io_task->pwrb_handle = alloc_wrb_handle(phba,
4059 beiscsi_conn->beiscsi_conn_cid -
4060 phba->fw_config.iscsi_cid_start);
4061 if (!io_task->pwrb_handle)
4062 goto free_io_hndls;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304063 } else {
4064 io_task->scsi_cmnd = NULL;
Jayamohan Kallickald7aea672010-01-05 05:08:39 +05304065 if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304066 if (!beiscsi_conn->login_in_progress) {
4067 spin_lock(&phba->mgmt_sgl_lock);
4068 io_task->psgl_handle = (struct sgl_handle *)
4069 alloc_mgmt_sgl_handle(phba);
4070 spin_unlock(&phba->mgmt_sgl_lock);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304071 if (!io_task->psgl_handle)
4072 goto free_hndls;
4073
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304074 beiscsi_conn->login_in_progress = 1;
4075 beiscsi_conn->plogin_sgl_handle =
4076 io_task->psgl_handle;
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304077 io_task->pwrb_handle =
4078 alloc_wrb_handle(phba,
4079 beiscsi_conn->beiscsi_conn_cid -
4080 phba->fw_config.iscsi_cid_start);
4081 if (!io_task->pwrb_handle)
4082 goto free_io_hndls;
4083 beiscsi_conn->plogin_wrb_handle =
4084 io_task->pwrb_handle;
4085
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304086 } else {
4087 io_task->psgl_handle =
4088 beiscsi_conn->plogin_sgl_handle;
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304089 io_task->pwrb_handle =
4090 beiscsi_conn->plogin_wrb_handle;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304091 }
Mike Christie1282ab72012-04-18 03:06:00 -05004092 beiscsi_conn->task = task;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304093 } else {
4094 spin_lock(&phba->mgmt_sgl_lock);
4095 io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
4096 spin_unlock(&phba->mgmt_sgl_lock);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304097 if (!io_task->psgl_handle)
4098 goto free_hndls;
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304099 io_task->pwrb_handle =
4100 alloc_wrb_handle(phba,
4101 beiscsi_conn->beiscsi_conn_cid -
4102 phba->fw_config.iscsi_cid_start);
4103 if (!io_task->pwrb_handle)
4104 goto free_mgmt_hndls;
4105
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304106 }
4107 }
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304108 itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle->
4109 wrb_index << 16) | (unsigned int)
4110 (io_task->psgl_handle->sgl_index));
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304111 io_task->pwrb_handle->pio_handle = task;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304112
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304113 io_task->cmd_bhs->iscsi_hdr.itt = itt;
4114 return 0;
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304115
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304116free_io_hndls:
4117 spin_lock(&phba->io_sgl_lock);
4118 free_io_sgl_handle(phba, io_task->psgl_handle);
4119 spin_unlock(&phba->io_sgl_lock);
4120 goto free_hndls;
4121free_mgmt_hndls:
4122 spin_lock(&phba->mgmt_sgl_lock);
4123 free_mgmt_sgl_handle(phba, io_task->psgl_handle);
4124 spin_unlock(&phba->mgmt_sgl_lock);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304125free_hndls:
4126 phwi_ctrlr = phba->phwi_ctrlr;
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05304127 pwrb_context = &phwi_ctrlr->wrb_context[
4128 beiscsi_conn->beiscsi_conn_cid -
4129 phba->fw_config.iscsi_cid_start];
Jayamohan Kallickald2cecf02010-07-22 04:25:40 +05304130 if (io_task->pwrb_handle)
4131 free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304132 io_task->pwrb_handle = NULL;
4133 pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
4134 io_task->bhs_pa.u.a64.address);
Mike Christie1282ab72012-04-18 03:06:00 -05004135 io_task->cmd_bhs = NULL;
John Soni Jose99bc5d52012-08-20 23:00:18 +05304136 beiscsi_log(phba, KERN_ERR,
4137 BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
4138 "BM_%d : Alloc of SGL_ICD Failed\n");
Jayamohan Kallickal2afc95b2009-09-22 08:22:26 +05304139 return -ENOMEM;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304140}
4141
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304142static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
4143 unsigned int num_sg, unsigned int xferlen,
4144 unsigned int writedir)
4145{
4146
4147 struct beiscsi_io_task *io_task = task->dd_data;
4148 struct iscsi_conn *conn = task->conn;
4149 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
4150 struct beiscsi_hba *phba = beiscsi_conn->phba;
4151 struct iscsi_wrb *pwrb = NULL;
4152 unsigned int doorbell = 0;
4153
4154 pwrb = io_task->pwrb_handle->pwrb;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304155 io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
4156 io_task->bhs_len = sizeof(struct be_cmd_bhs);
4157
4158 if (writedir) {
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304159 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4160 INI_WR_CMD);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304161 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304162 } else {
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304163 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4164 INI_RD_CMD);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304165 AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);
4166 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304167
4168 AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb,
Jayamohan Kallickaldc63aac2012-04-03 23:41:36 -05004169 cpu_to_be16(*(unsigned short *)
4170 &io_task->cmd_bhs->iscsi_hdr.lun));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304171 AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);
4172 AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
4173 io_task->pwrb_handle->wrb_index);
4174 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
4175 be32_to_cpu(task->cmdsn));
4176 AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
4177 io_task->psgl_handle->sgl_index);
4178
4179 hwi_write_sgl(pwrb, sg, num_sg, io_task);
4180
4181 AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
4182 io_task->pwrb_handle->nxt_wrb_index);
4183 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
4184
4185 doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304186 doorbell |= (io_task->pwrb_handle->wrb_index &
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304187 DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
4188 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
4189
4190 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
4191 return 0;
4192}
4193
4194static int beiscsi_mtask(struct iscsi_task *task)
4195{
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05304196 struct beiscsi_io_task *io_task = task->dd_data;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304197 struct iscsi_conn *conn = task->conn;
4198 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
4199 struct beiscsi_hba *phba = beiscsi_conn->phba;
4200 struct iscsi_wrb *pwrb = NULL;
4201 unsigned int doorbell = 0;
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05304202 unsigned int cid;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304203
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304204 cid = beiscsi_conn->beiscsi_conn_cid;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304205 pwrb = io_task->pwrb_handle->pwrb;
Jayamohan Kallickalcaf818f2010-01-23 05:38:18 +05304206 memset(pwrb, 0, sizeof(*pwrb));
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304207 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
4208 be32_to_cpu(task->cmdsn));
4209 AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,
4210 io_task->pwrb_handle->wrb_index);
4211 AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb,
4212 io_task->psgl_handle->sgl_index);
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05304213
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304214 switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
4215 case ISCSI_OP_LOGIN:
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304216 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4217 TGT_DM_CMD);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304218 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
4219 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
4220 hwi_write_buffer(pwrb, task);
4221 break;
4222 case ISCSI_OP_NOOP_OUT:
Jayamohan Kallickal1390b012011-03-25 14:24:01 -07004223 if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
4224 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4225 TGT_DM_CMD);
4226 AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
4227 pwrb, 0);
Jayamohan Kallickal685e16f2011-10-07 19:31:09 -05004228 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
Jayamohan Kallickal1390b012011-03-25 14:24:01 -07004229 } else {
4230 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4231 INI_RD_CMD);
Jayamohan Kallickal685e16f2011-10-07 19:31:09 -05004232 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
Jayamohan Kallickal1390b012011-03-25 14:24:01 -07004233 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304234 hwi_write_buffer(pwrb, task);
4235 break;
4236 case ISCSI_OP_TEXT:
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304237 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
Jayamohan Kallickalb30c6da2010-01-23 05:38:56 +05304238 TGT_DM_CMD);
Jayamohan Kallickal0ecb0b42010-01-05 05:09:19 +05304239 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304240 hwi_write_buffer(pwrb, task);
4241 break;
4242 case ISCSI_OP_SCSI_TMFUNC:
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304243 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
4244 INI_TMF_CMD);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304245 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
4246 hwi_write_buffer(pwrb, task);
4247 break;
4248 case ISCSI_OP_LOGOUT:
4249 AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
4250 AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
Jayamohan Kallickaldafab8e2010-02-20 08:03:56 +05304251 HWH_TYPE_LOGOUT);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304252 hwi_write_buffer(pwrb, task);
4253 break;
4254
4255 default:
John Soni Jose99bc5d52012-08-20 23:00:18 +05304256 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
4257 "BM_%d : opcode =%d Not supported\n",
4258 task->hdr->opcode & ISCSI_OPCODE_MASK);
4259
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304260 return -EINVAL;
4261 }
4262
4263 AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
Jayamohan Kallickal51a46252010-01-05 05:10:01 +05304264 task->data_count);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304265 AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
4266 io_task->pwrb_handle->nxt_wrb_index);
4267 be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
4268
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304269 doorbell |= cid & DB_WRB_POST_CID_MASK;
Jayamohan Kallickal32951dd2010-01-23 05:34:24 +05304270 doorbell |= (io_task->pwrb_handle->wrb_index &
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304271 DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;
4272 doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
4273 iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET);
4274 return 0;
4275}
4276
4277static int beiscsi_task_xmit(struct iscsi_task *task)
4278{
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304279 struct beiscsi_io_task *io_task = task->dd_data;
4280 struct scsi_cmnd *sc = task->sc;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304281 struct scatterlist *sg;
4282 int num_sg;
4283 unsigned int writedir = 0, xferlen = 0;
4284
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304285 if (!sc)
4286 return beiscsi_mtask(task);
4287
4288 io_task->scsi_cmnd = sc;
4289 num_sg = scsi_dma_map(sc);
4290 if (num_sg < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304291 struct iscsi_conn *conn = task->conn;
4292 struct beiscsi_hba *phba = NULL;
4293
4294 phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
4295 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO,
4296 "BM_%d : scsi_dma_map Failed\n");
4297
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304298 return num_sg;
4299 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304300 xferlen = scsi_bufflen(sc);
4301 sg = scsi_sglist(sc);
John Soni Jose99bc5d52012-08-20 23:00:18 +05304302 if (sc->sc_data_direction == DMA_TO_DEVICE)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304303 writedir = 1;
John Soni Jose99bc5d52012-08-20 23:00:18 +05304304 else
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304305 writedir = 0;
John Soni Jose99bc5d52012-08-20 23:00:18 +05304306
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304307 return beiscsi_iotask(task, sg, num_sg, xferlen, writedir);
4308}
4309
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004310/**
4311 * beiscsi_bsg_request - handle bsg request from ISCSI transport
4312 * @job: job to handle
4313 */
4314static int beiscsi_bsg_request(struct bsg_job *job)
4315{
4316 struct Scsi_Host *shost;
4317 struct beiscsi_hba *phba;
4318 struct iscsi_bsg_request *bsg_req = job->request;
4319 int rc = -EINVAL;
4320 unsigned int tag;
4321 struct be_dma_mem nonemb_cmd;
4322 struct be_cmd_resp_hdr *resp;
4323 struct iscsi_bsg_reply *bsg_reply = job->reply;
4324 unsigned short status, extd_status;
4325
4326 shost = iscsi_job_to_shost(job);
4327 phba = iscsi_host_priv(shost);
4328
4329 switch (bsg_req->msgcode) {
4330 case ISCSI_BSG_HST_VENDOR:
4331 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
4332 job->request_payload.payload_len,
4333 &nonemb_cmd.dma);
4334 if (nonemb_cmd.va == NULL) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304335 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
4336 "BM_%d : Failed to allocate memory for "
4337 "beiscsi_bsg_request\n");
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004338 return -EIO;
4339 }
4340 tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job,
4341 &nonemb_cmd);
4342 if (!tag) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304343 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
4344 "BM_%d : be_cmd_get_mac_addr Failed\n");
4345
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004346 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
4347 nonemb_cmd.va, nonemb_cmd.dma);
4348 return -EAGAIN;
4349 } else
4350 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
4351 phba->ctrl.mcc_numtag[tag]);
4352 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
4353 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
4354 free_mcc_tag(&phba->ctrl, tag);
4355 resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va;
4356 sg_copy_from_buffer(job->reply_payload.sg_list,
4357 job->reply_payload.sg_cnt,
4358 nonemb_cmd.va, (resp->response_length
4359 + sizeof(*resp)));
4360 bsg_reply->reply_payload_rcv_len = resp->response_length;
4361 bsg_reply->result = status;
4362 bsg_job_done(job, bsg_reply->result,
4363 bsg_reply->reply_payload_rcv_len);
4364 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
4365 nonemb_cmd.va, nonemb_cmd.dma);
4366 if (status || extd_status) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304367 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
4368 "BM_%d : be_cmd_get_mac_addr Failed"
4369 " status = %d extd_status = %d\n",
4370 status, extd_status);
4371
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004372 return -EIO;
4373 }
4374 break;
4375
4376 default:
John Soni Jose99bc5d52012-08-20 23:00:18 +05304377 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
4378 "BM_%d : Unsupported bsg command: 0x%x\n",
4379 bsg_req->msgcode);
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004380 break;
4381 }
4382
4383 return rc;
4384}
4385
John Soni Jose99bc5d52012-08-20 23:00:18 +05304386void beiscsi_hba_attrs_init(struct beiscsi_hba *phba)
4387{
4388 /* Set the logging parameter */
4389 beiscsi_log_enable_init(phba, beiscsi_log_enable);
4390}
4391
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004392static void beiscsi_quiesce(struct beiscsi_hba *phba)
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304393{
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304394 struct hwi_controller *phwi_ctrlr;
4395 struct hwi_context_memory *phwi_context;
4396 struct be_eq_obj *pbe_eq;
4397 unsigned int i, msix_vec;
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304398 u8 *real_offset = 0;
4399 u32 value = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304400
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304401 phwi_ctrlr = phba->phwi_ctrlr;
4402 phwi_context = phwi_ctrlr->phwi_ctxt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304403 hwi_disable_intr(phba);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304404 if (phba->msix_enabled) {
4405 for (i = 0; i <= phba->num_cpus; i++) {
4406 msix_vec = phba->msix_entries[i].vector;
4407 free_irq(msix_vec, &phwi_context->be_eq[i]);
Jayamohan Kallickal8fcfb212011-08-24 16:05:30 -07004408 kfree(phba->msi_name[i]);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304409 }
4410 } else
4411 if (phba->pcidev->irq)
4412 free_irq(phba->pcidev->irq, phba);
4413 pci_disable_msix(phba->pcidev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304414 destroy_workqueue(phba->wq);
4415 if (blk_iopoll_enabled)
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304416 for (i = 0; i < phba->num_cpus; i++) {
4417 pbe_eq = &phwi_context->be_eq[i];
4418 blk_iopoll_disable(&pbe_eq->iopoll);
4419 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304420
4421 beiscsi_clean_port(phba);
4422 beiscsi_free_mem(phba);
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304423 real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
4424
4425 value = readl((void *)real_offset);
4426
4427 if (value & 0x00010000) {
4428 value &= 0xfffeffff;
4429 writel(value, (void *)real_offset);
4430 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304431 beiscsi_unmap_pci_function(phba);
4432 pci_free_consistent(phba->pcidev,
4433 phba->ctrl.mbox_mem_alloced.size,
4434 phba->ctrl.mbox_mem_alloced.va,
4435 phba->ctrl.mbox_mem_alloced.dma);
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004436}
4437
4438static void beiscsi_remove(struct pci_dev *pcidev)
4439{
4440
4441 struct beiscsi_hba *phba = NULL;
4442
4443 phba = pci_get_drvdata(pcidev);
4444 if (!phba) {
4445 dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n");
4446 return;
4447 }
4448
Mike Christie0e438952012-04-03 23:41:51 -05004449 beiscsi_destroy_def_ifaces(phba);
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004450 beiscsi_quiesce(phba);
Mike Christie9d045162011-06-24 15:11:52 -05004451 iscsi_boot_destroy_kset(phba->boot_kset);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304452 iscsi_host_remove(phba->shost);
4453 pci_dev_put(phba->pcidev);
4454 iscsi_host_free(phba->shost);
Jayamohan Kallickal8dce69f2011-08-22 10:08:29 -07004455 pci_disable_device(pcidev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304456}
4457
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004458static void beiscsi_shutdown(struct pci_dev *pcidev)
4459{
4460
4461 struct beiscsi_hba *phba = NULL;
4462
4463 phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
4464 if (!phba) {
4465 dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n");
4466 return;
4467 }
4468
4469 beiscsi_quiesce(phba);
Jayamohan Kallickal8dce69f2011-08-22 10:08:29 -07004470 pci_disable_device(pcidev);
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004471}
4472
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304473static void beiscsi_msix_enable(struct beiscsi_hba *phba)
4474{
4475 int i, status;
4476
4477 for (i = 0; i <= phba->num_cpus; i++)
4478 phba->msix_entries[i].entry = i;
4479
4480 status = pci_enable_msix(phba->pcidev, phba->msix_entries,
4481 (phba->num_cpus + 1));
4482 if (!status)
4483 phba->msix_enabled = true;
4484
4485 return;
4486}
4487
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304488static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
4489 const struct pci_device_id *id)
4490{
4491 struct beiscsi_hba *phba = NULL;
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304492 struct hwi_controller *phwi_ctrlr;
4493 struct hwi_context_memory *phwi_context;
4494 struct be_eq_obj *pbe_eq;
Jayamohan Kallickal238f6b72010-07-22 04:23:22 +05304495 int ret, num_cpus, i;
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304496 u8 *real_offset = 0;
4497 u32 value = 0;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304498
4499 ret = beiscsi_enable_pci(pcidev);
4500 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304501 dev_err(&pcidev->dev,
4502 "beiscsi_dev_probe - Failed to enable pci device\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304503 return ret;
4504 }
4505
4506 phba = beiscsi_hba_alloc(pcidev);
4507 if (!phba) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304508 dev_err(&pcidev->dev,
4509 "beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304510 goto disable_pci;
4511 }
4512
John Soni Jose99bc5d52012-08-20 23:00:18 +05304513 /* Initialize Driver configuration Paramters */
4514 beiscsi_hba_attrs_init(phba);
4515
Jayamohan Kallickalf98c96b2010-02-11 05:11:15 +05304516 switch (pcidev->device) {
4517 case BE_DEVICE_ID1:
4518 case OC_DEVICE_ID1:
4519 case OC_DEVICE_ID2:
4520 phba->generation = BE_GEN2;
4521 break;
4522 case BE_DEVICE_ID2:
4523 case OC_DEVICE_ID3:
4524 phba->generation = BE_GEN3;
4525 break;
4526 default:
4527 phba->generation = 0;
4528 }
4529
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304530 if (enable_msix)
4531 num_cpus = find_num_cpus();
4532 else
4533 num_cpus = 1;
4534 phba->num_cpus = num_cpus;
John Soni Jose99bc5d52012-08-20 23:00:18 +05304535 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
4536 "BM_%d : num_cpus = %d\n",
4537 phba->num_cpus);
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304538
Jayamohan Kallickalb547f2d2012-04-03 23:41:41 -05004539 if (enable_msix) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304540 beiscsi_msix_enable(phba);
Jayamohan Kallickalb547f2d2012-04-03 23:41:41 -05004541 if (!phba->msix_enabled)
4542 phba->num_cpus = 1;
4543 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304544 ret = be_ctrl_init(phba, pcidev);
4545 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304546 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4547 "BM_%d : beiscsi_dev_probe-"
4548 "Failed in be_ctrl_init\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304549 goto hba_free;
4550 }
4551
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304552 if (!num_hba) {
4553 real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
4554 value = readl((void *)real_offset);
4555 if (value & 0x00010000) {
4556 gcrashmode++;
John Soni Jose99bc5d52012-08-20 23:00:18 +05304557 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4558 "BM_%d : Loading Driver in crashdump mode\n");
Jayamohan Kallickale5285862011-10-07 19:31:08 -05004559 ret = beiscsi_cmd_reset_function(phba);
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304560 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304561 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4562 "BM_%d : Reset Failed. Aborting Crashdump\n");
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304563 goto hba_free;
4564 }
4565 ret = be_chk_reset_complete(phba);
4566 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304567 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4568 "BM_%d : Failed to get out of reset."
4569 "Aborting Crashdump\n");
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304570 goto hba_free;
4571 }
4572 } else {
4573 value |= 0x00010000;
4574 writel(value, (void *)real_offset);
4575 num_hba++;
4576 }
4577 }
4578
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304579 spin_lock_init(&phba->io_sgl_lock);
4580 spin_lock_init(&phba->mgmt_sgl_lock);
4581 spin_lock_init(&phba->isr_lock);
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05304582 ret = mgmt_get_fw_config(&phba->ctrl, phba);
4583 if (ret != 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304584 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4585 "BM_%d : Error getting fw config\n");
Jayamohan Kallickal7da50872010-01-05 05:04:12 +05304586 goto free_port;
4587 }
4588 phba->shost->max_id = phba->fw_config.iscsi_cid_count;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304589 beiscsi_get_params(phba);
Jayamohan Kallickalaa874f02010-01-05 05:12:03 +05304590 phba->shost->can_queue = phba->params.ios_per_ctrl;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304591 ret = beiscsi_init_port(phba);
4592 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304593 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4594 "BM_%d : beiscsi_dev_probe-"
4595 "Failed in beiscsi_init_port\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304596 goto free_port;
4597 }
4598
Jayamohan Kallickal756d29c2010-01-05 05:10:46 +05304599 for (i = 0; i < MAX_MCC_CMD ; i++) {
4600 init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);
4601 phba->ctrl.mcc_tag[i] = i + 1;
4602 phba->ctrl.mcc_numtag[i + 1] = 0;
4603 phba->ctrl.mcc_tag_available++;
4604 }
4605
4606 phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
4607
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304608 snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
4609 phba->shost->host_no);
Tejun Heo278274d2011-02-01 11:42:42 +01004610 phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304611 if (!phba->wq) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304612 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4613 "BM_%d : beiscsi_dev_probe-"
4614 "Failed to allocate work queue\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304615 goto free_twq;
4616 }
4617
4618 INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs);
4619
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304620 phwi_ctrlr = phba->phwi_ctrlr;
4621 phwi_context = phwi_ctrlr->phwi_ctxt;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304622 if (blk_iopoll_enabled) {
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304623 for (i = 0; i < phba->num_cpus; i++) {
4624 pbe_eq = &phwi_context->be_eq[i];
4625 blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget,
4626 be_iopoll);
4627 blk_iopoll_enable(&pbe_eq->iopoll);
4628 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304629 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304630 ret = beiscsi_init_irqs(phba);
4631 if (ret < 0) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304632 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4633 "BM_%d : beiscsi_dev_probe-"
4634 "Failed to beiscsi_init_irqs\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304635 goto free_blkenbld;
4636 }
Jayamohan Kallickal238f6b72010-07-22 04:23:22 +05304637 hwi_enable_intr(phba);
Mike Christief457a462011-06-24 15:11:53 -05004638
4639 if (beiscsi_setup_boot_info(phba))
4640 /*
4641 * log error but continue, because we may not be using
4642 * iscsi boot.
4643 */
John Soni Jose99bc5d52012-08-20 23:00:18 +05304644 beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
4645 "BM_%d : Could not set up "
4646 "iSCSI boot info.\n");
Mike Christief457a462011-06-24 15:11:53 -05004647
Mike Christie0e438952012-04-03 23:41:51 -05004648 beiscsi_create_def_ifaces(phba);
John Soni Jose99bc5d52012-08-20 23:00:18 +05304649 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
4650 "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304651 return 0;
4652
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304653free_blkenbld:
4654 destroy_workqueue(phba->wq);
4655 if (blk_iopoll_enabled)
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304656 for (i = 0; i < phba->num_cpus; i++) {
4657 pbe_eq = &phwi_context->be_eq[i];
4658 blk_iopoll_disable(&pbe_eq->iopoll);
4659 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304660free_twq:
4661 beiscsi_clean_port(phba);
4662 beiscsi_free_mem(phba);
4663free_port:
Jayamohan Kallickale9b91192010-07-22 04:24:53 +05304664 real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
4665
4666 value = readl((void *)real_offset);
4667
4668 if (value & 0x00010000) {
4669 value &= 0xfffeffff;
4670 writel(value, (void *)real_offset);
4671 }
4672
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304673 pci_free_consistent(phba->pcidev,
4674 phba->ctrl.mbox_mem_alloced.size,
4675 phba->ctrl.mbox_mem_alloced.va,
4676 phba->ctrl.mbox_mem_alloced.dma);
4677 beiscsi_unmap_pci_function(phba);
4678hba_free:
Jayamohan Kallickal238f6b72010-07-22 04:23:22 +05304679 if (phba->msix_enabled)
4680 pci_disable_msix(phba->pcidev);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304681 iscsi_host_remove(phba->shost);
4682 pci_dev_put(phba->pcidev);
4683 iscsi_host_free(phba->shost);
4684disable_pci:
4685 pci_disable_device(pcidev);
4686 return ret;
4687}
4688
4689struct iscsi_transport beiscsi_iscsi_transport = {
4690 .owner = THIS_MODULE,
4691 .name = DRV_NAME,
Jayamohan Kallickal9db0fb32010-01-05 05:12:43 +05304692 .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304693 CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304694 .create_session = beiscsi_session_create,
4695 .destroy_session = beiscsi_session_destroy,
4696 .create_conn = beiscsi_conn_create,
4697 .bind_conn = beiscsi_conn_bind,
4698 .destroy_conn = iscsi_conn_teardown,
Mike Christie3128c6c2011-07-25 13:48:42 -05004699 .attr_is_visible = be2iscsi_attr_is_visible,
Mike Christie0e438952012-04-03 23:41:51 -05004700 .set_iface_param = be2iscsi_iface_set_param,
4701 .get_iface_param = be2iscsi_iface_get_param,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304702 .set_param = beiscsi_set_param,
Mike Christiec7f7fd52011-02-16 15:04:41 -06004703 .get_conn_param = iscsi_conn_get_param,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304704 .get_session_param = iscsi_session_get_param,
4705 .get_host_param = beiscsi_get_host_param,
4706 .start_conn = beiscsi_conn_start,
Mike Christiefa95d202010-06-09 03:30:08 -05004707 .stop_conn = iscsi_conn_stop,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304708 .send_pdu = iscsi_conn_send_pdu,
4709 .xmit_task = beiscsi_task_xmit,
4710 .cleanup_task = beiscsi_cleanup_task,
4711 .alloc_pdu = beiscsi_alloc_pdu,
4712 .parse_pdu_itt = beiscsi_parse_pdu,
4713 .get_stats = beiscsi_conn_get_stats,
Mike Christiec7f7fd52011-02-16 15:04:41 -06004714 .get_ep_param = beiscsi_ep_get_param,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304715 .ep_connect = beiscsi_ep_connect,
4716 .ep_poll = beiscsi_ep_poll,
4717 .ep_disconnect = beiscsi_ep_disconnect,
4718 .session_recovery_timedout = iscsi_session_recovery_timedout,
Jayamohan Kallickalffce3e22012-04-03 23:41:50 -05004719 .bsg_request = beiscsi_bsg_request,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304720};
4721
4722static struct pci_driver beiscsi_pci_driver = {
4723 .name = DRV_NAME,
4724 .probe = beiscsi_dev_probe,
4725 .remove = beiscsi_remove,
Jayamohan Kallickal25602c92011-08-22 10:08:28 -07004726 .shutdown = beiscsi_shutdown,
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304727 .id_table = beiscsi_pci_id_table
4728};
4729
Jayamohan Kallickalbfead3b2009-10-23 11:52:33 +05304730
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304731static int __init beiscsi_module_init(void)
4732{
4733 int ret;
4734
4735 beiscsi_scsi_transport =
4736 iscsi_register_transport(&beiscsi_iscsi_transport);
4737 if (!beiscsi_scsi_transport) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304738 printk(KERN_ERR
4739 "beiscsi_module_init - Unable to register beiscsi transport.\n");
Jayamohan Kallickalf55a24f2010-01-23 05:37:40 +05304740 return -ENOMEM;
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304741 }
John Soni Jose99bc5d52012-08-20 23:00:18 +05304742 printk(KERN_INFO "In beiscsi_module_init, tt=%p\n",
4743 &beiscsi_iscsi_transport);
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304744
4745 ret = pci_register_driver(&beiscsi_pci_driver);
4746 if (ret) {
John Soni Jose99bc5d52012-08-20 23:00:18 +05304747 printk(KERN_ERR
4748 "beiscsi_module_init - Unable to register beiscsi pci driver.\n");
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304749 goto unregister_iscsi_transport;
4750 }
Jayamohan Kallickal6733b392009-09-05 07:36:35 +05304751 return 0;
4752
4753unregister_iscsi_transport:
4754 iscsi_unregister_transport(&beiscsi_iscsi_transport);
4755 return ret;
4756}
4757
4758static void __exit beiscsi_module_exit(void)
4759{
4760 pci_unregister_driver(&beiscsi_pci_driver);
4761 iscsi_unregister_transport(&beiscsi_iscsi_transport);
4762}
4763
4764module_init(beiscsi_module_init);
4765module_exit(beiscsi_module_exit);