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