diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 22:25:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 22:25:38 -0500 |
commit | 0d522ee7499e4abe7189b2f1728e838959b8ddde (patch) | |
tree | 094f60e8bdb0083b58a43a0decbca59443a66e39 | |
parent | 5eea9be8b2478dbc2f9fb1cd6228a90e8dba804e (diff) | |
parent | 323f6226a816f0b01514d25fba5529e0e68636c3 (diff) |
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley:
"This patch set is driver updates for qla4xxx, scsi_debug, pm80xx,
fcoe/libfc, eas2r, lpfc, be2iscsi and megaraid_sas plus some assorted
bug fixes and cleanups"
* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (106 commits)
[SCSI] scsi_error: Escalate to LUN reset if abort fails
[SCSI] Add 'eh_deadline' to limit SCSI EH runtime
[SCSI] remove check for 'resetting'
[SCSI] dc395: Move 'last_reset' into internal host structure
[SCSI] tmscsim: Move 'last_reset' into host structure
[SCSI] advansys: Remove 'last_reset' references
[SCSI] dpt_i2o: return SCSI_MLQUEUE_HOST_BUSY when in reset
[SCSI] dpt_i2o: Remove DPTI_STATE_IOCTL
[SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path
[SCSI] lpfc: Fix typo on NULL assignment
[SCSI] scsi_dh_alua: ALUA handler attach should succeed while TPG is transitioning
[SCSI] scsi_dh_alua: ALUA check sense should retry device internal reset unit attention
[SCSI] esas2r: Cleanup snprinf formatting of firmware version
[SCSI] esas2r: Remove superfluous mask of pcie_cap_reg
[SCSI] esas2r: Fixes for big-endian platforms
[SCSI] esas2r: Directly call kernel functions for atomic bit operations
[SCSI] lpfc 8.3.43: Update lpfc version to driver version 8.3.43
[SCSI] lpfc 8.3.43: Fixed not processing task management IOCB response status
[SCSI] lpfc 8.3.43: Fixed spinlock hang.
[SCSI] lpfc 8.3.43: Fixed invalid Total_Data_Placed value received for els and ct command responses
...
92 files changed, 5591 insertions, 1420 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 67c0068b7a0f..647d21877d7e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1867,7 +1867,7 @@ S: Supported | |||
1867 | F: drivers/net/wireless/brcm80211/ | 1867 | F: drivers/net/wireless/brcm80211/ |
1868 | 1868 | ||
1869 | BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER | 1869 | BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER |
1870 | M: Bhanu Prakash Gollapudi <bprakash@broadcom.com> | 1870 | M: Eddie Wai <eddie.wai@broadcom.com> |
1871 | L: linux-scsi@vger.kernel.org | 1871 | L: linux-scsi@vger.kernel.org |
1872 | S: Supported | 1872 | S: Supported |
1873 | F: drivers/scsi/bnx2fc/ | 1873 | F: drivers/scsi/bnx2fc/ |
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 757eb0716d45..972f8176665f 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
@@ -26,8 +26,8 @@ | |||
26 | 26 | ||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define blogic_drvr_version "2.1.16" | 29 | #define blogic_drvr_version "2.1.17" |
30 | #define blogic_drvr_date "18 July 2002" | 30 | #define blogic_drvr_date "12 September 2013" |
31 | 31 | ||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -311,12 +311,14 @@ static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter) | |||
311 | caller. | 311 | caller. |
312 | */ | 312 | */ |
313 | 313 | ||
314 | static void blogic_dealloc_ccb(struct blogic_ccb *ccb) | 314 | static void blogic_dealloc_ccb(struct blogic_ccb *ccb, int dma_unmap) |
315 | { | 315 | { |
316 | struct blogic_adapter *adapter = ccb->adapter; | 316 | struct blogic_adapter *adapter = ccb->adapter; |
317 | 317 | ||
318 | scsi_dma_unmap(ccb->command); | 318 | if (ccb->command != NULL) |
319 | pci_unmap_single(adapter->pci_device, ccb->sensedata, | 319 | scsi_dma_unmap(ccb->command); |
320 | if (dma_unmap) | ||
321 | pci_unmap_single(adapter->pci_device, ccb->sensedata, | ||
320 | ccb->sense_datalen, PCI_DMA_FROMDEVICE); | 322 | ccb->sense_datalen, PCI_DMA_FROMDEVICE); |
321 | 323 | ||
322 | ccb->command = NULL; | 324 | ccb->command = NULL; |
@@ -2762,8 +2764,8 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) | |||
2762 | /* | 2764 | /* |
2763 | Place CCB back on the Host Adapter's free list. | 2765 | Place CCB back on the Host Adapter's free list. |
2764 | */ | 2766 | */ |
2765 | blogic_dealloc_ccb(ccb); | 2767 | blogic_dealloc_ccb(ccb, 1); |
2766 | #if 0 /* this needs to be redone different for new EH */ | 2768 | #if 0 /* this needs to be redone different for new EH */ |
2767 | /* | 2769 | /* |
2768 | Bus Device Reset CCBs have the command field | 2770 | Bus Device Reset CCBs have the command field |
2769 | non-NULL only when a Bus Device Reset was requested | 2771 | non-NULL only when a Bus Device Reset was requested |
@@ -2791,7 +2793,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) | |||
2791 | if (ccb->status == BLOGIC_CCB_RESET && | 2793 | if (ccb->status == BLOGIC_CCB_RESET && |
2792 | ccb->tgt_id == tgt_id) { | 2794 | ccb->tgt_id == tgt_id) { |
2793 | command = ccb->command; | 2795 | command = ccb->command; |
2794 | blogic_dealloc_ccb(ccb); | 2796 | blogic_dealloc_ccb(ccb, 1); |
2795 | adapter->active_cmds[tgt_id]--; | 2797 | adapter->active_cmds[tgt_id]--; |
2796 | command->result = DID_RESET << 16; | 2798 | command->result = DID_RESET << 16; |
2797 | command->scsi_done(command); | 2799 | command->scsi_done(command); |
@@ -2862,7 +2864,7 @@ static void blogic_process_ccbs(struct blogic_adapter *adapter) | |||
2862 | /* | 2864 | /* |
2863 | Place CCB back on the Host Adapter's free list. | 2865 | Place CCB back on the Host Adapter's free list. |
2864 | */ | 2866 | */ |
2865 | blogic_dealloc_ccb(ccb); | 2867 | blogic_dealloc_ccb(ccb, 1); |
2866 | /* | 2868 | /* |
2867 | Call the SCSI Command Completion Routine. | 2869 | Call the SCSI Command Completion Routine. |
2868 | */ | 2870 | */ |
@@ -3034,6 +3036,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, | |||
3034 | int buflen = scsi_bufflen(command); | 3036 | int buflen = scsi_bufflen(command); |
3035 | int count; | 3037 | int count; |
3036 | struct blogic_ccb *ccb; | 3038 | struct blogic_ccb *ccb; |
3039 | dma_addr_t sense_buf; | ||
3037 | 3040 | ||
3038 | /* | 3041 | /* |
3039 | SCSI REQUEST_SENSE commands will be executed automatically by the | 3042 | SCSI REQUEST_SENSE commands will be executed automatically by the |
@@ -3179,10 +3182,17 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, | |||
3179 | } | 3182 | } |
3180 | memcpy(ccb->cdb, cdb, cdblen); | 3183 | memcpy(ccb->cdb, cdb, cdblen); |
3181 | ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE; | 3184 | ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE; |
3182 | ccb->sensedata = pci_map_single(adapter->pci_device, | 3185 | ccb->command = command; |
3186 | sense_buf = pci_map_single(adapter->pci_device, | ||
3183 | command->sense_buffer, ccb->sense_datalen, | 3187 | command->sense_buffer, ccb->sense_datalen, |
3184 | PCI_DMA_FROMDEVICE); | 3188 | PCI_DMA_FROMDEVICE); |
3185 | ccb->command = command; | 3189 | if (dma_mapping_error(&adapter->pci_device->dev, sense_buf)) { |
3190 | blogic_err("DMA mapping for sense data buffer failed\n", | ||
3191 | adapter); | ||
3192 | blogic_dealloc_ccb(ccb, 0); | ||
3193 | return SCSI_MLQUEUE_HOST_BUSY; | ||
3194 | } | ||
3195 | ccb->sensedata = sense_buf; | ||
3186 | command->scsi_done = comp_cb; | 3196 | command->scsi_done = comp_cb; |
3187 | if (blogic_multimaster_type(adapter)) { | 3197 | if (blogic_multimaster_type(adapter)) { |
3188 | /* | 3198 | /* |
@@ -3203,7 +3213,7 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command, | |||
3203 | if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, | 3213 | if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, |
3204 | ccb)) { | 3214 | ccb)) { |
3205 | blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter); | 3215 | blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter); |
3206 | blogic_dealloc_ccb(ccb); | 3216 | blogic_dealloc_ccb(ccb, 1); |
3207 | command->result = DID_ERROR << 16; | 3217 | command->result = DID_ERROR << 16; |
3208 | command->scsi_done(command); | 3218 | command->scsi_done(command); |
3209 | } | 3219 | } |
@@ -3337,7 +3347,7 @@ static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset) | |||
3337 | 3347 | ||
3338 | for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all) | 3348 | for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all) |
3339 | if (ccb->status == BLOGIC_CCB_ACTIVE) | 3349 | if (ccb->status == BLOGIC_CCB_ACTIVE) |
3340 | blogic_dealloc_ccb(ccb); | 3350 | blogic_dealloc_ccb(ccb, 1); |
3341 | /* | 3351 | /* |
3342 | * Wait a few seconds between the Host Adapter Hard Reset which | 3352 | * Wait a few seconds between the Host Adapter Hard Reset which |
3343 | * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some | 3353 | * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some |
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index c67e401954c5..d8145888e66a 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -2511,8 +2511,8 @@ static void asc_prt_scsi_host(struct Scsi_Host *s) | |||
2511 | struct asc_board *boardp = shost_priv(s); | 2511 | struct asc_board *boardp = shost_priv(s); |
2512 | 2512 | ||
2513 | printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); | 2513 | printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); |
2514 | printk(" host_busy %u, host_no %d, last_reset %d,\n", | 2514 | printk(" host_busy %u, host_no %d,\n", |
2515 | s->host_busy, s->host_no, (unsigned)s->last_reset); | 2515 | s->host_busy, s->host_no); |
2516 | 2516 | ||
2517 | printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", | 2517 | printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", |
2518 | (ulong)s->base, (ulong)s->io_port, boardp->irq); | 2518 | (ulong)s->base, (ulong)s->io_port, boardp->irq); |
@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) | |||
3345 | shost->host_no); | 3345 | shost->host_no); |
3346 | 3346 | ||
3347 | seq_printf(m, | 3347 | seq_printf(m, |
3348 | " host_busy %u, last_reset %lu, max_id %u, max_lun %u, max_channel %u\n", | 3348 | " host_busy %u, max_id %u, max_lun %u, max_channel %u\n", |
3349 | shost->host_busy, shost->last_reset, shost->max_id, | 3349 | shost->host_busy, shost->max_id, |
3350 | shost->max_lun, shost->max_channel); | 3350 | shost->max_lun, shost->max_channel); |
3351 | 3351 | ||
3352 | seq_printf(m, | 3352 | seq_printf(m, |
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 777e7c0bbb4b..2e28f6c419fe 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h | |||
@@ -128,7 +128,7 @@ struct be_ctrl_info { | |||
128 | 128 | ||
129 | #define PAGE_SHIFT_4K 12 | 129 | #define PAGE_SHIFT_4K 12 |
130 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) | 130 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) |
131 | #define mcc_timeout 120000 /* 5s timeout */ | 131 | #define mcc_timeout 120000 /* 12s timeout */ |
132 | 132 | ||
133 | /* Returns number of pages spanned by the data starting at the given addr */ | 133 | /* Returns number of pages spanned by the data starting at the given addr */ |
134 | #define PAGES_4K_SPANNED(_address, size) \ | 134 | #define PAGES_4K_SPANNED(_address, size) \ |
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index e66aa7c11a8a..3338391b64de 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -17,9 +17,9 @@ | |||
17 | 17 | ||
18 | #include <scsi/iscsi_proto.h> | 18 | #include <scsi/iscsi_proto.h> |
19 | 19 | ||
20 | #include "be_main.h" | ||
20 | #include "be.h" | 21 | #include "be.h" |
21 | #include "be_mgmt.h" | 22 | #include "be_mgmt.h" |
22 | #include "be_main.h" | ||
23 | 23 | ||
24 | int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) | 24 | int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) |
25 | { | 25 | { |
@@ -158,8 +158,10 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
158 | struct be_cmd_resp_hdr *ioctl_resp_hdr; | 158 | struct be_cmd_resp_hdr *ioctl_resp_hdr; |
159 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 159 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
160 | 160 | ||
161 | if (beiscsi_error(phba)) | 161 | if (beiscsi_error(phba)) { |
162 | free_mcc_tag(&phba->ctrl, tag); | ||
162 | return -EIO; | 163 | return -EIO; |
164 | } | ||
163 | 165 | ||
164 | /* wait for the mccq completion */ | 166 | /* wait for the mccq completion */ |
165 | rc = wait_event_interruptible_timeout( | 167 | rc = wait_event_interruptible_timeout( |
@@ -173,7 +175,11 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
173 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | 175 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | |
174 | BEISCSI_LOG_CONFIG, | 176 | BEISCSI_LOG_CONFIG, |
175 | "BC_%d : MBX Cmd Completion timed out\n"); | 177 | "BC_%d : MBX Cmd Completion timed out\n"); |
176 | rc = -EAGAIN; | 178 | rc = -EBUSY; |
179 | |||
180 | /* decrement the mccq used count */ | ||
181 | atomic_dec(&phba->ctrl.mcc_obj.q.used); | ||
182 | |||
177 | goto release_mcc_tag; | 183 | goto release_mcc_tag; |
178 | } else | 184 | } else |
179 | rc = 0; | 185 | rc = 0; |
@@ -208,10 +214,18 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
208 | 214 | ||
209 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { | 215 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { |
210 | ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; | 216 | ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; |
211 | if (ioctl_resp_hdr->response_length) | 217 | beiscsi_log(phba, KERN_WARNING, |
212 | goto release_mcc_tag; | 218 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | |
219 | BEISCSI_LOG_CONFIG, | ||
220 | "BC_%d : Insufficent Buffer Error " | ||
221 | "Resp_Len : %d Actual_Resp_Len : %d\n", | ||
222 | ioctl_resp_hdr->response_length, | ||
223 | ioctl_resp_hdr->actual_resp_len); | ||
224 | |||
225 | rc = -EAGAIN; | ||
226 | goto release_mcc_tag; | ||
213 | } | 227 | } |
214 | rc = -EAGAIN; | 228 | rc = -EIO; |
215 | } | 229 | } |
216 | 230 | ||
217 | release_mcc_tag: | 231 | release_mcc_tag: |
@@ -363,7 +377,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, | |||
363 | } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || | 377 | } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || |
364 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && | 378 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && |
365 | (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { | 379 | (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { |
366 | phba->state = BE_ADAPTER_UP; | 380 | phba->state = BE_ADAPTER_LINK_UP; |
367 | 381 | ||
368 | beiscsi_log(phba, KERN_ERR, | 382 | beiscsi_log(phba, KERN_ERR, |
369 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | 383 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, |
@@ -486,33 +500,47 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) | |||
486 | **/ | 500 | **/ |
487 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | 501 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) |
488 | { | 502 | { |
503 | #define BEISCSI_MBX_RDY_BIT_TIMEOUT 4000 /* 4sec */ | ||
489 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 504 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; |
490 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | 505 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
491 | uint32_t wait = 0; | 506 | unsigned long timeout; |
507 | bool read_flag = false; | ||
508 | int ret = 0, i; | ||
492 | u32 ready; | 509 | u32 ready; |
510 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); | ||
493 | 511 | ||
494 | do { | 512 | if (beiscsi_error(phba)) |
513 | return -EIO; | ||
495 | 514 | ||
496 | if (beiscsi_error(phba)) | 515 | timeout = jiffies + (HZ * 110); |
497 | return -EIO; | ||
498 | 516 | ||
499 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; | 517 | do { |
500 | if (ready) | 518 | for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { |
501 | break; | 519 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; |
520 | if (ready) { | ||
521 | read_flag = true; | ||
522 | break; | ||
523 | } | ||
524 | mdelay(1); | ||
525 | } | ||
502 | 526 | ||
503 | if (wait > BEISCSI_HOST_MBX_TIMEOUT) { | 527 | if (!read_flag) { |
504 | beiscsi_log(phba, KERN_ERR, | 528 | wait_event_timeout(rdybit_check_q, |
505 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 529 | (read_flag != true), |
506 | "BC_%d : FW Timed Out\n"); | 530 | HZ * 5); |
531 | } | ||
532 | } while ((time_before(jiffies, timeout)) && !read_flag); | ||
533 | |||
534 | if (!read_flag) { | ||
535 | beiscsi_log(phba, KERN_ERR, | ||
536 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
537 | "BC_%d : FW Timed Out\n"); | ||
507 | phba->fw_timeout = true; | 538 | phba->fw_timeout = true; |
508 | beiscsi_ue_detect(phba); | 539 | beiscsi_ue_detect(phba); |
509 | return -EBUSY; | 540 | ret = -EBUSY; |
510 | } | 541 | } |
511 | 542 | ||
512 | mdelay(1); | 543 | return ret; |
513 | wait++; | ||
514 | } while (true); | ||
515 | return 0; | ||
516 | } | 544 | } |
517 | 545 | ||
518 | /* | 546 | /* |
@@ -699,7 +727,7 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba) | |||
699 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 727 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
700 | struct be_mcc_wrb *wrb; | 728 | struct be_mcc_wrb *wrb; |
701 | 729 | ||
702 | BUG_ON(atomic_read(&mccq->used) >= mccq->len); | 730 | WARN_ON(atomic_read(&mccq->used) >= mccq->len); |
703 | wrb = queue_head_node(mccq); | 731 | wrb = queue_head_node(mccq); |
704 | memset(wrb, 0, sizeof(*wrb)); | 732 | memset(wrb, 0, sizeof(*wrb)); |
705 | wrb->tag0 = (mccq->head & 0x000000FF) << 16; | 733 | wrb->tag0 = (mccq->head & 0x000000FF) << 16; |
@@ -1009,10 +1037,29 @@ int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | |||
1009 | return status; | 1037 | return status; |
1010 | } | 1038 | } |
1011 | 1039 | ||
1040 | /** | ||
1041 | * be_cmd_create_default_pdu_queue()- Create DEFQ for the adapter | ||
1042 | * @ctrl: ptr to ctrl_info | ||
1043 | * @cq: Completion Queue | ||
1044 | * @dq: Default Queue | ||
1045 | * @lenght: ring size | ||
1046 | * @entry_size: size of each entry in DEFQ | ||
1047 | * @is_header: Header or Data DEFQ | ||
1048 | * @ulp_num: Bind to which ULP | ||
1049 | * | ||
1050 | * Create HDR/Data DEFQ for the passed ULP. Unsol PDU are posted | ||
1051 | * on this queue by the FW | ||
1052 | * | ||
1053 | * return | ||
1054 | * Success: 0 | ||
1055 | * Failure: Non-Zero Value | ||
1056 | * | ||
1057 | **/ | ||
1012 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | 1058 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, |
1013 | struct be_queue_info *cq, | 1059 | struct be_queue_info *cq, |
1014 | struct be_queue_info *dq, int length, | 1060 | struct be_queue_info *dq, int length, |
1015 | int entry_size) | 1061 | int entry_size, uint8_t is_header, |
1062 | uint8_t ulp_num) | ||
1016 | { | 1063 | { |
1017 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 1064 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
1018 | struct be_defq_create_req *req = embedded_payload(wrb); | 1065 | struct be_defq_create_req *req = embedded_payload(wrb); |
@@ -1030,6 +1077,11 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | |||
1030 | OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); | 1077 | OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); |
1031 | 1078 | ||
1032 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 1079 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); |
1080 | if (phba->fw_config.dual_ulp_aware) { | ||
1081 | req->ulp_num = ulp_num; | ||
1082 | req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT); | ||
1083 | req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT); | ||
1084 | } | ||
1033 | 1085 | ||
1034 | if (is_chip_be2_be3r(phba)) { | 1086 | if (is_chip_be2_be3r(phba)) { |
1035 | AMAP_SET_BITS(struct amap_be_default_pdu_context, | 1087 | AMAP_SET_BITS(struct amap_be_default_pdu_context, |
@@ -1067,22 +1119,53 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | |||
1067 | 1119 | ||
1068 | status = be_mbox_notify(ctrl); | 1120 | status = be_mbox_notify(ctrl); |
1069 | if (!status) { | 1121 | if (!status) { |
1122 | struct be_ring *defq_ring; | ||
1070 | struct be_defq_create_resp *resp = embedded_payload(wrb); | 1123 | struct be_defq_create_resp *resp = embedded_payload(wrb); |
1071 | 1124 | ||
1072 | dq->id = le16_to_cpu(resp->id); | 1125 | dq->id = le16_to_cpu(resp->id); |
1073 | dq->created = true; | 1126 | dq->created = true; |
1127 | if (is_header) | ||
1128 | defq_ring = &phba->phwi_ctrlr->default_pdu_hdr[ulp_num]; | ||
1129 | else | ||
1130 | defq_ring = &phba->phwi_ctrlr-> | ||
1131 | default_pdu_data[ulp_num]; | ||
1132 | |||
1133 | defq_ring->id = dq->id; | ||
1134 | |||
1135 | if (!phba->fw_config.dual_ulp_aware) { | ||
1136 | defq_ring->ulp_num = BEISCSI_ULP0; | ||
1137 | defq_ring->doorbell_offset = DB_RXULP0_OFFSET; | ||
1138 | } else { | ||
1139 | defq_ring->ulp_num = resp->ulp_num; | ||
1140 | defq_ring->doorbell_offset = resp->doorbell_offset; | ||
1141 | } | ||
1074 | } | 1142 | } |
1075 | spin_unlock(&ctrl->mbox_lock); | 1143 | spin_unlock(&ctrl->mbox_lock); |
1076 | 1144 | ||
1077 | return status; | 1145 | return status; |
1078 | } | 1146 | } |
1079 | 1147 | ||
1080 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | 1148 | /** |
1081 | struct be_queue_info *wrbq) | 1149 | * be_cmd_wrbq_create()- Create WRBQ |
1150 | * @ctrl: ptr to ctrl_info | ||
1151 | * @q_mem: memory details for the queue | ||
1152 | * @wrbq: queue info | ||
1153 | * @pwrb_context: ptr to wrb_context | ||
1154 | * @ulp_num: ULP on which the WRBQ is to be created | ||
1155 | * | ||
1156 | * Create WRBQ on the passed ULP_NUM. | ||
1157 | * | ||
1158 | **/ | ||
1159 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, | ||
1160 | struct be_dma_mem *q_mem, | ||
1161 | struct be_queue_info *wrbq, | ||
1162 | struct hwi_wrb_context *pwrb_context, | ||
1163 | uint8_t ulp_num) | ||
1082 | { | 1164 | { |
1083 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 1165 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
1084 | struct be_wrbq_create_req *req = embedded_payload(wrb); | 1166 | struct be_wrbq_create_req *req = embedded_payload(wrb); |
1085 | struct be_wrbq_create_resp *resp = embedded_payload(wrb); | 1167 | struct be_wrbq_create_resp *resp = embedded_payload(wrb); |
1168 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
1086 | int status; | 1169 | int status; |
1087 | 1170 | ||
1088 | spin_lock(&ctrl->mbox_lock); | 1171 | spin_lock(&ctrl->mbox_lock); |
@@ -1093,17 +1176,78 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | |||
1093 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 1176 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
1094 | OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); | 1177 | OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); |
1095 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 1178 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); |
1179 | |||
1180 | if (phba->fw_config.dual_ulp_aware) { | ||
1181 | req->ulp_num = ulp_num; | ||
1182 | req->dua_feature |= (1 << BEISCSI_DUAL_ULP_AWARE_BIT); | ||
1183 | req->dua_feature |= (1 << BEISCSI_BIND_Q_TO_ULP_BIT); | ||
1184 | } | ||
1185 | |||
1096 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 1186 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); |
1097 | 1187 | ||
1098 | status = be_mbox_notify(ctrl); | 1188 | status = be_mbox_notify(ctrl); |
1099 | if (!status) { | 1189 | if (!status) { |
1100 | wrbq->id = le16_to_cpu(resp->cid); | 1190 | wrbq->id = le16_to_cpu(resp->cid); |
1101 | wrbq->created = true; | 1191 | wrbq->created = true; |
1192 | |||
1193 | pwrb_context->cid = wrbq->id; | ||
1194 | if (!phba->fw_config.dual_ulp_aware) { | ||
1195 | pwrb_context->doorbell_offset = DB_TXULP0_OFFSET; | ||
1196 | pwrb_context->ulp_num = BEISCSI_ULP0; | ||
1197 | } else { | ||
1198 | pwrb_context->ulp_num = resp->ulp_num; | ||
1199 | pwrb_context->doorbell_offset = resp->doorbell_offset; | ||
1200 | } | ||
1102 | } | 1201 | } |
1103 | spin_unlock(&ctrl->mbox_lock); | 1202 | spin_unlock(&ctrl->mbox_lock); |
1104 | return status; | 1203 | return status; |
1105 | } | 1204 | } |
1106 | 1205 | ||
1206 | int be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl, | ||
1207 | struct be_dma_mem *q_mem) | ||
1208 | { | ||
1209 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
1210 | struct be_post_template_pages_req *req = embedded_payload(wrb); | ||
1211 | int status; | ||
1212 | |||
1213 | spin_lock(&ctrl->mbox_lock); | ||
1214 | |||
1215 | memset(wrb, 0, sizeof(*wrb)); | ||
1216 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
1217 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1218 | OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS, | ||
1219 | sizeof(*req)); | ||
1220 | |||
1221 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
1222 | req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI; | ||
1223 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
1224 | |||
1225 | status = be_mbox_notify(ctrl); | ||
1226 | spin_unlock(&ctrl->mbox_lock); | ||
1227 | return status; | ||
1228 | } | ||
1229 | |||
1230 | int be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl) | ||
1231 | { | ||
1232 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
1233 | struct be_remove_template_pages_req *req = embedded_payload(wrb); | ||
1234 | int status; | ||
1235 | |||
1236 | spin_lock(&ctrl->mbox_lock); | ||
1237 | |||
1238 | memset(wrb, 0, sizeof(*wrb)); | ||
1239 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
1240 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
1241 | OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS, | ||
1242 | sizeof(*req)); | ||
1243 | |||
1244 | req->type = BEISCSI_TEMPLATE_HDR_TYPE_ISCSI; | ||
1245 | |||
1246 | status = be_mbox_notify(ctrl); | ||
1247 | spin_unlock(&ctrl->mbox_lock); | ||
1248 | return status; | ||
1249 | } | ||
1250 | |||
1107 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | 1251 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, |
1108 | struct be_dma_mem *q_mem, | 1252 | struct be_dma_mem *q_mem, |
1109 | u32 page_offset, u32 num_pages) | 1253 | u32 page_offset, u32 num_pages) |
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 99073086dfe0..627ebbe0172c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -40,6 +40,7 @@ struct be_mcc_wrb { | |||
40 | u32 tag1; /* dword 3 */ | 40 | u32 tag1; /* dword 3 */ |
41 | u32 rsvd; /* dword 4 */ | 41 | u32 rsvd; /* dword 4 */ |
42 | union { | 42 | union { |
43 | #define EMBED_MBX_MAX_PAYLOAD_SIZE 220 | ||
43 | u8 embedded_payload[236]; /* used by embedded cmds */ | 44 | u8 embedded_payload[236]; /* used by embedded cmds */ |
44 | struct be_sge sgl[19]; /* used by non-embedded cmds */ | 45 | struct be_sge sgl[19]; /* used by non-embedded cmds */ |
45 | } payload; | 46 | } payload; |
@@ -162,6 +163,8 @@ struct be_mcc_mailbox { | |||
162 | #define OPCODE_COMMON_CQ_CREATE 12 | 163 | #define OPCODE_COMMON_CQ_CREATE 12 |
163 | #define OPCODE_COMMON_EQ_CREATE 13 | 164 | #define OPCODE_COMMON_EQ_CREATE 13 |
164 | #define OPCODE_COMMON_MCC_CREATE 21 | 165 | #define OPCODE_COMMON_MCC_CREATE 21 |
166 | #define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS 24 | ||
167 | #define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS 25 | ||
165 | #define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 | 168 | #define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 |
166 | #define OPCODE_COMMON_GET_FW_VERSION 35 | 169 | #define OPCODE_COMMON_GET_FW_VERSION 35 |
167 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | 170 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 |
@@ -217,6 +220,10 @@ struct phys_addr { | |||
217 | u32 hi; | 220 | u32 hi; |
218 | }; | 221 | }; |
219 | 222 | ||
223 | struct virt_addr { | ||
224 | u32 lo; | ||
225 | u32 hi; | ||
226 | }; | ||
220 | /************************** | 227 | /************************** |
221 | * BE Command definitions * | 228 | * BE Command definitions * |
222 | **************************/ | 229 | **************************/ |
@@ -722,7 +729,13 @@ int be_mbox_notify(struct be_ctrl_info *ctrl); | |||
722 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | 729 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, |
723 | struct be_queue_info *cq, | 730 | struct be_queue_info *cq, |
724 | struct be_queue_info *dq, int length, | 731 | struct be_queue_info *dq, int length, |
725 | int entry_size); | 732 | int entry_size, uint8_t is_header, |
733 | uint8_t ulp_num); | ||
734 | |||
735 | int be_cmd_iscsi_post_template_hdr(struct be_ctrl_info *ctrl, | ||
736 | struct be_dma_mem *q_mem); | ||
737 | |||
738 | int be_cmd_iscsi_remove_template_hdr(struct be_ctrl_info *ctrl); | ||
726 | 739 | ||
727 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | 740 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, |
728 | struct be_dma_mem *q_mem, u32 page_offset, | 741 | struct be_dma_mem *q_mem, u32 page_offset, |
@@ -731,7 +744,9 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | |||
731 | int beiscsi_cmd_reset_function(struct beiscsi_hba *phba); | 744 | int beiscsi_cmd_reset_function(struct beiscsi_hba *phba); |
732 | 745 | ||
733 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | 746 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, |
734 | struct be_queue_info *wrbq); | 747 | struct be_queue_info *wrbq, |
748 | struct hwi_wrb_context *pwrb_context, | ||
749 | uint8_t ulp_num); | ||
735 | 750 | ||
736 | bool is_link_state_evt(u32 trailer); | 751 | bool is_link_state_evt(u32 trailer); |
737 | 752 | ||
@@ -776,7 +791,9 @@ struct be_defq_create_req { | |||
776 | struct be_cmd_req_hdr hdr; | 791 | struct be_cmd_req_hdr hdr; |
777 | u16 num_pages; | 792 | u16 num_pages; |
778 | u8 ulp_num; | 793 | u8 ulp_num; |
779 | u8 rsvd0; | 794 | #define BEISCSI_DUAL_ULP_AWARE_BIT 0 /* Byte 3 - Bit 0 */ |
795 | #define BEISCSI_BIND_Q_TO_ULP_BIT 1 /* Byte 3 - Bit 1 */ | ||
796 | u8 dua_feature; | ||
780 | struct be_default_pdu_context context; | 797 | struct be_default_pdu_context context; |
781 | struct phys_addr pages[8]; | 798 | struct phys_addr pages[8]; |
782 | } __packed; | 799 | } __packed; |
@@ -784,6 +801,27 @@ struct be_defq_create_req { | |||
784 | struct be_defq_create_resp { | 801 | struct be_defq_create_resp { |
785 | struct be_cmd_req_hdr hdr; | 802 | struct be_cmd_req_hdr hdr; |
786 | u16 id; | 803 | u16 id; |
804 | u8 rsvd0; | ||
805 | u8 ulp_num; | ||
806 | u32 doorbell_offset; | ||
807 | u16 register_set; | ||
808 | u16 doorbell_format; | ||
809 | } __packed; | ||
810 | |||
811 | struct be_post_template_pages_req { | ||
812 | struct be_cmd_req_hdr hdr; | ||
813 | u16 num_pages; | ||
814 | #define BEISCSI_TEMPLATE_HDR_TYPE_ISCSI 0x1 | ||
815 | u16 type; | ||
816 | struct phys_addr scratch_pa; | ||
817 | struct virt_addr scratch_va; | ||
818 | struct virt_addr pages_va; | ||
819 | struct phys_addr pages[16]; | ||
820 | } __packed; | ||
821 | |||
822 | struct be_remove_template_pages_req { | ||
823 | struct be_cmd_req_hdr hdr; | ||
824 | u16 type; | ||
787 | u16 rsvd0; | 825 | u16 rsvd0; |
788 | } __packed; | 826 | } __packed; |
789 | 827 | ||
@@ -800,14 +838,18 @@ struct be_wrbq_create_req { | |||
800 | struct be_cmd_req_hdr hdr; | 838 | struct be_cmd_req_hdr hdr; |
801 | u16 num_pages; | 839 | u16 num_pages; |
802 | u8 ulp_num; | 840 | u8 ulp_num; |
803 | u8 rsvd0; | 841 | u8 dua_feature; |
804 | struct phys_addr pages[8]; | 842 | struct phys_addr pages[8]; |
805 | } __packed; | 843 | } __packed; |
806 | 844 | ||
807 | struct be_wrbq_create_resp { | 845 | struct be_wrbq_create_resp { |
808 | struct be_cmd_resp_hdr resp_hdr; | 846 | struct be_cmd_resp_hdr resp_hdr; |
809 | u16 cid; | 847 | u16 cid; |
810 | u16 rsvd0; | 848 | u8 rsvd0; |
849 | u8 ulp_num; | ||
850 | u32 doorbell_offset; | ||
851 | u16 register_set; | ||
852 | u16 doorbell_format; | ||
811 | } __packed; | 853 | } __packed; |
812 | 854 | ||
813 | #define SOL_CID_MASK 0x0000FFC0 | 855 | #define SOL_CID_MASK 0x0000FFC0 |
@@ -1002,6 +1044,7 @@ union tcp_upload_params { | |||
1002 | } __packed; | 1044 | } __packed; |
1003 | 1045 | ||
1004 | struct be_ulp_fw_cfg { | 1046 | struct be_ulp_fw_cfg { |
1047 | #define BEISCSI_ULP_ISCSI_INI_MODE 0x10 | ||
1005 | u32 ulp_mode; | 1048 | u32 ulp_mode; |
1006 | u32 etx_base; | 1049 | u32 etx_base; |
1007 | u32 etx_count; | 1050 | u32 etx_count; |
@@ -1017,14 +1060,26 @@ struct be_ulp_fw_cfg { | |||
1017 | u32 icd_count; | 1060 | u32 icd_count; |
1018 | }; | 1061 | }; |
1019 | 1062 | ||
1063 | struct be_ulp_chain_icd { | ||
1064 | u32 chain_base; | ||
1065 | u32 chain_count; | ||
1066 | }; | ||
1067 | |||
1020 | struct be_fw_cfg { | 1068 | struct be_fw_cfg { |
1021 | struct be_cmd_req_hdr hdr; | 1069 | struct be_cmd_req_hdr hdr; |
1022 | u32 be_config_number; | 1070 | u32 be_config_number; |
1023 | u32 asic_revision; | 1071 | u32 asic_revision; |
1024 | u32 phys_port; | 1072 | u32 phys_port; |
1073 | #define BEISCSI_FUNC_ISCSI_INI_MODE 0x10 | ||
1074 | #define BEISCSI_FUNC_DUA_MODE 0x800 | ||
1025 | u32 function_mode; | 1075 | u32 function_mode; |
1026 | struct be_ulp_fw_cfg ulp[2]; | 1076 | struct be_ulp_fw_cfg ulp[2]; |
1027 | u32 function_caps; | 1077 | u32 function_caps; |
1078 | u32 cqid_base; | ||
1079 | u32 cqid_count; | ||
1080 | u32 eqid_base; | ||
1081 | u32 eqid_count; | ||
1082 | struct be_ulp_chain_icd chain_icd[2]; | ||
1028 | } __packed; | 1083 | } __packed; |
1029 | 1084 | ||
1030 | struct be_cmd_get_all_if_id_req { | 1085 | struct be_cmd_get_all_if_id_req { |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index ef36be003f67..ffadbee0b4d9 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -58,10 +58,15 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | |||
58 | } | 58 | } |
59 | beiscsi_ep = ep->dd_data; | 59 | beiscsi_ep = ep->dd_data; |
60 | phba = beiscsi_ep->phba; | 60 | phba = beiscsi_ep->phba; |
61 | shost = phba->shost; | ||
62 | 61 | ||
63 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 62 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
64 | "BS_%d : In beiscsi_session_create\n"); | 63 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
64 | "BS_%d : PCI_ERROR Recovery\n"); | ||
65 | return NULL; | ||
66 | } else { | ||
67 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
68 | "BS_%d : In beiscsi_session_create\n"); | ||
69 | } | ||
65 | 70 | ||
66 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { | 71 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { |
67 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 72 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
@@ -74,6 +79,7 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | |||
74 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; | 79 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; |
75 | } | 80 | } |
76 | 81 | ||
82 | shost = phba->shost; | ||
77 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, | 83 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, |
78 | shost, cmds_max, | 84 | shost, cmds_max, |
79 | sizeof(*beiscsi_sess), | 85 | sizeof(*beiscsi_sess), |
@@ -194,6 +200,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
194 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 200 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
195 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 201 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
196 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 202 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
203 | struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr; | ||
204 | struct hwi_wrb_context *pwrb_context; | ||
197 | struct beiscsi_endpoint *beiscsi_ep; | 205 | struct beiscsi_endpoint *beiscsi_ep; |
198 | struct iscsi_endpoint *ep; | 206 | struct iscsi_endpoint *ep; |
199 | 207 | ||
@@ -214,9 +222,13 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, | |||
214 | return -EEXIST; | 222 | return -EEXIST; |
215 | } | 223 | } |
216 | 224 | ||
225 | pwrb_context = &phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID( | ||
226 | beiscsi_ep->ep_cid)]; | ||
227 | |||
217 | beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; | 228 | beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; |
218 | beiscsi_conn->ep = beiscsi_ep; | 229 | beiscsi_conn->ep = beiscsi_ep; |
219 | beiscsi_ep->conn = beiscsi_conn; | 230 | beiscsi_ep->conn = beiscsi_conn; |
231 | beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset; | ||
220 | 232 | ||
221 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 233 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
222 | "BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n", | 234 | "BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n", |
@@ -265,13 +277,17 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) | |||
265 | 277 | ||
266 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) | 278 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) |
267 | { | 279 | { |
268 | struct be_cmd_get_if_info_resp if_info; | 280 | struct be_cmd_get_if_info_resp *if_info; |
269 | 281 | ||
270 | if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) | 282 | if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) { |
271 | beiscsi_create_ipv4_iface(phba); | 283 | beiscsi_create_ipv4_iface(phba); |
284 | kfree(if_info); | ||
285 | } | ||
272 | 286 | ||
273 | if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) | 287 | if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) { |
274 | beiscsi_create_ipv6_iface(phba); | 288 | beiscsi_create_ipv6_iface(phba); |
289 | kfree(if_info); | ||
290 | } | ||
275 | } | 291 | } |
276 | 292 | ||
277 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) | 293 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) |
@@ -467,6 +483,12 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost, | |||
467 | uint32_t rm_len = dt_len; | 483 | uint32_t rm_len = dt_len; |
468 | int ret = 0 ; | 484 | int ret = 0 ; |
469 | 485 | ||
486 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
487 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
488 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
489 | return -EBUSY; | ||
490 | } | ||
491 | |||
470 | nla_for_each_attr(attrib, data, dt_len, rm_len) { | 492 | nla_for_each_attr(attrib, data, dt_len, rm_len) { |
471 | iface_param = nla_data(attrib); | 493 | iface_param = nla_data(attrib); |
472 | 494 | ||
@@ -512,59 +534,60 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, | |||
512 | struct iscsi_iface *iface, int param, | 534 | struct iscsi_iface *iface, int param, |
513 | char *buf) | 535 | char *buf) |
514 | { | 536 | { |
515 | struct be_cmd_get_if_info_resp if_info; | 537 | struct be_cmd_get_if_info_resp *if_info; |
516 | int len, ip_type = BE2_IPV4; | 538 | int len, ip_type = BE2_IPV4; |
517 | 539 | ||
518 | memset(&if_info, 0, sizeof(if_info)); | ||
519 | |||
520 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) | 540 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) |
521 | ip_type = BE2_IPV6; | 541 | ip_type = BE2_IPV6; |
522 | 542 | ||
523 | len = mgmt_get_if_info(phba, ip_type, &if_info); | 543 | len = mgmt_get_if_info(phba, ip_type, &if_info); |
524 | if (len) | 544 | if (len) { |
545 | kfree(if_info); | ||
525 | return len; | 546 | return len; |
547 | } | ||
526 | 548 | ||
527 | switch (param) { | 549 | switch (param) { |
528 | case ISCSI_NET_PARAM_IPV4_ADDR: | 550 | case ISCSI_NET_PARAM_IPV4_ADDR: |
529 | len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr); | 551 | len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr); |
530 | break; | 552 | break; |
531 | case ISCSI_NET_PARAM_IPV6_ADDR: | 553 | case ISCSI_NET_PARAM_IPV6_ADDR: |
532 | len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr); | 554 | len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr); |
533 | break; | 555 | break; |
534 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: | 556 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: |
535 | if (!if_info.dhcp_state) | 557 | if (!if_info->dhcp_state) |
536 | len = sprintf(buf, "static\n"); | 558 | len = sprintf(buf, "static\n"); |
537 | else | 559 | else |
538 | len = sprintf(buf, "dhcp\n"); | 560 | len = sprintf(buf, "dhcp\n"); |
539 | break; | 561 | break; |
540 | case ISCSI_NET_PARAM_IPV4_SUBNET: | 562 | case ISCSI_NET_PARAM_IPV4_SUBNET: |
541 | len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask); | 563 | len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask); |
542 | break; | 564 | break; |
543 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 565 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
544 | len = sprintf(buf, "%s\n", | 566 | len = sprintf(buf, "%s\n", |
545 | (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 567 | (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
546 | ? "Disabled\n" : "Enabled\n"); | 568 | ? "Disabled\n" : "Enabled\n"); |
547 | break; | 569 | break; |
548 | case ISCSI_NET_PARAM_VLAN_ID: | 570 | case ISCSI_NET_PARAM_VLAN_ID: |
549 | if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 571 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
550 | return -EINVAL; | 572 | return -EINVAL; |
551 | else | 573 | else |
552 | len = sprintf(buf, "%d\n", | 574 | len = sprintf(buf, "%d\n", |
553 | (if_info.vlan_priority & | 575 | (if_info->vlan_priority & |
554 | ISCSI_MAX_VLAN_ID)); | 576 | ISCSI_MAX_VLAN_ID)); |
555 | break; | 577 | break; |
556 | case ISCSI_NET_PARAM_VLAN_PRIORITY: | 578 | case ISCSI_NET_PARAM_VLAN_PRIORITY: |
557 | if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE) | 579 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
558 | return -EINVAL; | 580 | return -EINVAL; |
559 | else | 581 | else |
560 | len = sprintf(buf, "%d\n", | 582 | len = sprintf(buf, "%d\n", |
561 | ((if_info.vlan_priority >> 13) & | 583 | ((if_info->vlan_priority >> 13) & |
562 | ISCSI_MAX_VLAN_PRIORITY)); | 584 | ISCSI_MAX_VLAN_PRIORITY)); |
563 | break; | 585 | break; |
564 | default: | 586 | default: |
565 | WARN_ON(1); | 587 | WARN_ON(1); |
566 | } | 588 | } |
567 | 589 | ||
590 | kfree(if_info); | ||
568 | return len; | 591 | return len; |
569 | } | 592 | } |
570 | 593 | ||
@@ -577,6 +600,12 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, | |||
577 | struct be_cmd_get_def_gateway_resp gateway; | 600 | struct be_cmd_get_def_gateway_resp gateway; |
578 | int len = -ENOSYS; | 601 | int len = -ENOSYS; |
579 | 602 | ||
603 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
604 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
605 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
606 | return -EBUSY; | ||
607 | } | ||
608 | |||
580 | switch (param) { | 609 | switch (param) { |
581 | case ISCSI_NET_PARAM_IPV4_ADDR: | 610 | case ISCSI_NET_PARAM_IPV4_ADDR: |
582 | case ISCSI_NET_PARAM_IPV4_SUBNET: | 611 | case ISCSI_NET_PARAM_IPV4_SUBNET: |
@@ -672,8 +701,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
672 | session->max_burst = 262144; | 701 | session->max_burst = 262144; |
673 | break; | 702 | break; |
674 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: | 703 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: |
675 | if ((conn->max_xmit_dlength > 65536) || | 704 | if (conn->max_xmit_dlength > 65536) |
676 | (conn->max_xmit_dlength == 0)) | ||
677 | conn->max_xmit_dlength = 65536; | 705 | conn->max_xmit_dlength = 65536; |
678 | default: | 706 | default: |
679 | return 0; | 707 | return 0; |
@@ -727,7 +755,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) | |||
727 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 755 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
728 | struct iscsi_cls_host *ihost = shost->shost_data; | 756 | struct iscsi_cls_host *ihost = shost->shost_data; |
729 | 757 | ||
730 | ihost->port_state = (phba->state == BE_ADAPTER_UP) ? | 758 | ihost->port_state = (phba->state == BE_ADAPTER_LINK_UP) ? |
731 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; | 759 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; |
732 | } | 760 | } |
733 | 761 | ||
@@ -795,9 +823,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
795 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 823 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
796 | int status = 0; | 824 | int status = 0; |
797 | 825 | ||
798 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 826 | |
799 | "BS_%d : In beiscsi_get_host_param," | 827 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
800 | " param= %d\n", param); | 828 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
829 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
830 | return -EBUSY; | ||
831 | } else { | ||
832 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
833 | "BS_%d : In beiscsi_get_host_param," | ||
834 | " param = %d\n", param); | ||
835 | } | ||
801 | 836 | ||
802 | switch (param) { | 837 | switch (param) { |
803 | case ISCSI_HOST_PARAM_HWADDRESS: | 838 | case ISCSI_HOST_PARAM_HWADDRESS: |
@@ -840,7 +875,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | |||
840 | struct be_cmd_get_nic_conf_resp resp; | 875 | struct be_cmd_get_nic_conf_resp resp; |
841 | int rc; | 876 | int rc; |
842 | 877 | ||
843 | if (strlen(phba->mac_address)) | 878 | if (phba->mac_addr_set) |
844 | return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); | 879 | return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); |
845 | 880 | ||
846 | memset(&resp, 0, sizeof(resp)); | 881 | memset(&resp, 0, sizeof(resp)); |
@@ -848,6 +883,7 @@ int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | |||
848 | if (rc) | 883 | if (rc) |
849 | return rc; | 884 | return rc; |
850 | 885 | ||
886 | phba->mac_addr_set = true; | ||
851 | memcpy(phba->mac_address, resp.mac_address, ETH_ALEN); | 887 | memcpy(phba->mac_address, resp.mac_address, ETH_ALEN); |
852 | return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); | 888 | return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); |
853 | } | 889 | } |
@@ -923,6 +959,10 @@ static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, | |||
923 | session->max_r2t); | 959 | session->max_r2t); |
924 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, | 960 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, |
925 | (conn->exp_statsn - 1)); | 961 | (conn->exp_statsn - 1)); |
962 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, | ||
963 | max_recv_data_segment_length, params, | ||
964 | conn->max_recv_dlength); | ||
965 | |||
926 | } | 966 | } |
927 | 967 | ||
928 | /** | 968 | /** |
@@ -935,10 +975,19 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
935 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 975 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
936 | struct beiscsi_endpoint *beiscsi_ep; | 976 | struct beiscsi_endpoint *beiscsi_ep; |
937 | struct beiscsi_offload_params params; | 977 | struct beiscsi_offload_params params; |
978 | struct beiscsi_hba *phba; | ||
938 | 979 | ||
939 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, | 980 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; |
940 | BEISCSI_LOG_CONFIG, | 981 | |
941 | "BS_%d : In beiscsi_conn_start\n"); | 982 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
983 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
984 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
985 | return -EBUSY; | ||
986 | } else { | ||
987 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, | ||
988 | BEISCSI_LOG_CONFIG, | ||
989 | "BS_%d : In beiscsi_conn_start\n"); | ||
990 | } | ||
942 | 991 | ||
943 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 992 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
944 | beiscsi_ep = beiscsi_conn->ep; | 993 | beiscsi_ep = beiscsi_conn->ep; |
@@ -960,15 +1009,31 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
960 | */ | 1009 | */ |
961 | static int beiscsi_get_cid(struct beiscsi_hba *phba) | 1010 | static int beiscsi_get_cid(struct beiscsi_hba *phba) |
962 | { | 1011 | { |
963 | unsigned short cid = 0xFFFF; | 1012 | unsigned short cid = 0xFFFF, cid_from_ulp; |
964 | 1013 | struct ulp_cid_info *cid_info = NULL; | |
965 | if (!phba->avlbl_cids) | 1014 | uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; |
966 | return cid; | 1015 | |
967 | 1016 | /* Find the ULP which has more CID available */ | |
968 | cid = phba->cid_array[phba->cid_alloc++]; | 1017 | cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? |
969 | if (phba->cid_alloc == phba->params.cxns_per_ctrl) | 1018 | BEISCSI_ULP0_AVLBL_CID(phba) : 0; |
970 | phba->cid_alloc = 0; | 1019 | cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ? |
971 | phba->avlbl_cids--; | 1020 | BEISCSI_ULP1_AVLBL_CID(phba) : 0; |
1021 | cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? | ||
1022 | BEISCSI_ULP0 : BEISCSI_ULP1; | ||
1023 | |||
1024 | if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) { | ||
1025 | cid_info = phba->cid_array_info[cid_from_ulp]; | ||
1026 | if (!cid_info->avlbl_cids) | ||
1027 | return cid; | ||
1028 | |||
1029 | cid = cid_info->cid_array[cid_info->cid_alloc++]; | ||
1030 | |||
1031 | if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT( | ||
1032 | phba, cid_from_ulp)) | ||
1033 | cid_info->cid_alloc = 0; | ||
1034 | |||
1035 | cid_info->avlbl_cids--; | ||
1036 | } | ||
972 | return cid; | 1037 | return cid; |
973 | } | 1038 | } |
974 | 1039 | ||
@@ -979,10 +1044,22 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba) | |||
979 | */ | 1044 | */ |
980 | static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | 1045 | static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) |
981 | { | 1046 | { |
982 | phba->avlbl_cids++; | 1047 | uint16_t cid_post_ulp; |
983 | phba->cid_array[phba->cid_free++] = cid; | 1048 | struct hwi_controller *phwi_ctrlr; |
984 | if (phba->cid_free == phba->params.cxns_per_ctrl) | 1049 | struct hwi_wrb_context *pwrb_context; |
985 | phba->cid_free = 0; | 1050 | struct ulp_cid_info *cid_info = NULL; |
1051 | uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); | ||
1052 | |||
1053 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1054 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; | ||
1055 | cid_post_ulp = pwrb_context->ulp_num; | ||
1056 | |||
1057 | cid_info = phba->cid_array_info[cid_post_ulp]; | ||
1058 | cid_info->avlbl_cids++; | ||
1059 | |||
1060 | cid_info->cid_array[cid_info->cid_free++] = cid; | ||
1061 | if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) | ||
1062 | cid_info->cid_free = 0; | ||
986 | } | 1063 | } |
987 | 1064 | ||
988 | /** | 1065 | /** |
@@ -1135,7 +1212,12 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
1135 | return ERR_PTR(ret); | 1212 | return ERR_PTR(ret); |
1136 | } | 1213 | } |
1137 | 1214 | ||
1138 | if (phba->state != BE_ADAPTER_UP) { | 1215 | if (phba->state & BE_ADAPTER_PCI_ERR) { |
1216 | ret = -EBUSY; | ||
1217 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
1218 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
1219 | return ERR_PTR(ret); | ||
1220 | } else if (phba->state & BE_ADAPTER_LINK_DOWN) { | ||
1139 | ret = -EBUSY; | 1221 | ret = -EBUSY; |
1140 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 1222 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
1141 | "BS_%d : The Adapter Port state is Down!!!\n"); | 1223 | "BS_%d : The Adapter Port state is Down!!!\n"); |
@@ -1260,6 +1342,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
1260 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; | 1342 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; |
1261 | } | 1343 | } |
1262 | 1344 | ||
1345 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
1346 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
1347 | "BS_%d : PCI_ERROR Recovery\n"); | ||
1348 | goto free_ep; | ||
1349 | } | ||
1350 | |||
1263 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, | 1351 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, |
1264 | beiscsi_ep->ep_cid, | 1352 | beiscsi_ep->ep_cid, |
1265 | mgmt_invalidate_flag, | 1353 | mgmt_invalidate_flag, |
@@ -1272,6 +1360,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
1272 | 1360 | ||
1273 | beiscsi_mccq_compl(phba, tag, NULL, NULL); | 1361 | beiscsi_mccq_compl(phba, tag, NULL, NULL); |
1274 | beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); | 1362 | beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); |
1363 | free_ep: | ||
1275 | beiscsi_free_ep(beiscsi_ep); | 1364 | beiscsi_free_ep(beiscsi_ep); |
1276 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | 1365 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); |
1277 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | 1366 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a1f5ac7a9806..1f375051483a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -149,18 +149,25 @@ BEISCSI_RW_ATTR(log_enable, 0x00, | |||
149 | "\t\t\t\tMiscellaneous Events : 0x04\n" | 149 | "\t\t\t\tMiscellaneous Events : 0x04\n" |
150 | "\t\t\t\tError Handling : 0x08\n" | 150 | "\t\t\t\tError Handling : 0x08\n" |
151 | "\t\t\t\tIO Path Events : 0x10\n" | 151 | "\t\t\t\tIO Path Events : 0x10\n" |
152 | "\t\t\t\tConfiguration Path : 0x20\n"); | 152 | "\t\t\t\tConfiguration Path : 0x20\n" |
153 | "\t\t\t\tiSCSI Protocol : 0x40\n"); | ||
153 | 154 | ||
154 | DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); | 155 | DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); |
155 | DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); | 156 | DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); |
156 | DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); | 157 | DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); |
157 | DEVICE_ATTR(beiscsi_active_cid_count, S_IRUGO, beiscsi_active_cid_disp, NULL); | 158 | DEVICE_ATTR(beiscsi_phys_port, S_IRUGO, beiscsi_phys_port_disp, NULL); |
159 | DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, | ||
160 | beiscsi_active_session_disp, NULL); | ||
161 | DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, | ||
162 | beiscsi_free_session_disp, NULL); | ||
158 | struct device_attribute *beiscsi_attrs[] = { | 163 | struct device_attribute *beiscsi_attrs[] = { |
159 | &dev_attr_beiscsi_log_enable, | 164 | &dev_attr_beiscsi_log_enable, |
160 | &dev_attr_beiscsi_drvr_ver, | 165 | &dev_attr_beiscsi_drvr_ver, |
161 | &dev_attr_beiscsi_adapter_family, | 166 | &dev_attr_beiscsi_adapter_family, |
162 | &dev_attr_beiscsi_fw_ver, | 167 | &dev_attr_beiscsi_fw_ver, |
163 | &dev_attr_beiscsi_active_cid_count, | 168 | &dev_attr_beiscsi_active_session_count, |
169 | &dev_attr_beiscsi_free_session_count, | ||
170 | &dev_attr_beiscsi_phys_port, | ||
164 | NULL, | 171 | NULL, |
165 | }; | 172 | }; |
166 | 173 | ||
@@ -239,6 +246,11 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) | |||
239 | return SUCCESS; | 246 | return SUCCESS; |
240 | } | 247 | } |
241 | spin_unlock_bh(&session->lock); | 248 | spin_unlock_bh(&session->lock); |
249 | /* Invalidate WRB Posted for this Task */ | ||
250 | AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | ||
251 | aborted_io_task->pwrb_handle->pwrb, | ||
252 | 1); | ||
253 | |||
242 | conn = aborted_task->conn; | 254 | conn = aborted_task->conn; |
243 | beiscsi_conn = conn->dd_data; | 255 | beiscsi_conn = conn->dd_data; |
244 | phba = beiscsi_conn->phba; | 256 | phba = beiscsi_conn->phba; |
@@ -316,6 +328,11 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
316 | if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) | 328 | if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) |
317 | continue; | 329 | continue; |
318 | 330 | ||
331 | /* Invalidate WRB Posted for this Task */ | ||
332 | AMAP_SET_BITS(struct amap_iscsi_wrb, invld, | ||
333 | abrt_io_task->pwrb_handle->pwrb, | ||
334 | 1); | ||
335 | |||
319 | inv_tbl->cid = cid; | 336 | inv_tbl->cid = cid; |
320 | inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; | 337 | inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index; |
321 | num_invalidate++; | 338 | num_invalidate++; |
@@ -699,30 +716,85 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) | |||
699 | return status; | 716 | return status; |
700 | } | 717 | } |
701 | 718 | ||
719 | /** | ||
720 | * beiscsi_get_params()- Set the config paramters | ||
721 | * @phba: ptr device priv structure | ||
722 | **/ | ||
702 | static void beiscsi_get_params(struct beiscsi_hba *phba) | 723 | static void beiscsi_get_params(struct beiscsi_hba *phba) |
703 | { | 724 | { |
704 | phba->params.ios_per_ctrl = (phba->fw_config.iscsi_icd_count | 725 | uint32_t total_cid_count = 0; |
705 | - (phba->fw_config.iscsi_cid_count | 726 | uint32_t total_icd_count = 0; |
706 | + BE2_TMFS | 727 | uint8_t ulp_num = 0; |
707 | + BE2_NOPOUT_REQ)); | 728 | |
708 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; | 729 | total_cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + |
709 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count; | 730 | BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); |
710 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count; | 731 | |
732 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
733 | uint32_t align_mask = 0; | ||
734 | uint32_t icd_post_per_page = 0; | ||
735 | uint32_t icd_count_unavailable = 0; | ||
736 | uint32_t icd_start = 0, icd_count = 0; | ||
737 | uint32_t icd_start_align = 0, icd_count_align = 0; | ||
738 | |||
739 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
740 | icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; | ||
741 | icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; | ||
742 | |||
743 | /* Get ICD count that can be posted on each page */ | ||
744 | icd_post_per_page = (PAGE_SIZE / (BE2_SGE * | ||
745 | sizeof(struct iscsi_sge))); | ||
746 | align_mask = (icd_post_per_page - 1); | ||
747 | |||
748 | /* Check if icd_start is aligned ICD per page posting */ | ||
749 | if (icd_start % icd_post_per_page) { | ||
750 | icd_start_align = ((icd_start + | ||
751 | icd_post_per_page) & | ||
752 | ~(align_mask)); | ||
753 | phba->fw_config. | ||
754 | iscsi_icd_start[ulp_num] = | ||
755 | icd_start_align; | ||
756 | } | ||
757 | |||
758 | icd_count_align = (icd_count & ~align_mask); | ||
759 | |||
760 | /* ICD discarded in the process of alignment */ | ||
761 | if (icd_start_align) | ||
762 | icd_count_unavailable = ((icd_start_align - | ||
763 | icd_start) + | ||
764 | (icd_count - | ||
765 | icd_count_align)); | ||
766 | |||
767 | /* Updated ICD count available */ | ||
768 | phba->fw_config.iscsi_icd_count[ulp_num] = (icd_count - | ||
769 | icd_count_unavailable); | ||
770 | |||
771 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
772 | "BM_%d : Aligned ICD values\n" | ||
773 | "\t ICD Start : %d\n" | ||
774 | "\t ICD Count : %d\n" | ||
775 | "\t ICD Discarded : %d\n", | ||
776 | phba->fw_config. | ||
777 | iscsi_icd_start[ulp_num], | ||
778 | phba->fw_config. | ||
779 | iscsi_icd_count[ulp_num], | ||
780 | icd_count_unavailable); | ||
781 | break; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | total_icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; | ||
786 | phba->params.ios_per_ctrl = (total_icd_count - | ||
787 | (total_cid_count + | ||
788 | BE2_TMFS + BE2_NOPOUT_REQ)); | ||
789 | phba->params.cxns_per_ctrl = total_cid_count; | ||
790 | phba->params.asyncpdus_per_ctrl = total_cid_count; | ||
791 | phba->params.icds_per_ctrl = total_icd_count; | ||
711 | phba->params.num_sge_per_io = BE2_SGE; | 792 | phba->params.num_sge_per_io = BE2_SGE; |
712 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; | 793 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; |
713 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; | 794 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; |
714 | phba->params.eq_timer = 64; | 795 | phba->params.eq_timer = 64; |
715 | phba->params.num_eq_entries = | 796 | phba->params.num_eq_entries = 1024; |
716 | (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 | 797 | phba->params.num_cq_entries = 1024; |
717 | + BE2_TMFS) / 512) + 1) * 512; | ||
718 | phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) | ||
719 | ? 1024 : phba->params.num_eq_entries; | ||
720 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
721 | "BM_%d : phba->params.num_eq_entries=%d\n", | ||
722 | phba->params.num_eq_entries); | ||
723 | phba->params.num_cq_entries = | ||
724 | (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 | ||
725 | + BE2_TMFS) / 512) + 1) * 512; | ||
726 | phba->params.wrbs_per_cxn = 256; | 798 | phba->params.wrbs_per_cxn = 256; |
727 | } | 799 | } |
728 | 800 | ||
@@ -1613,8 +1685,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba, | |||
1613 | 1685 | ||
1614 | WARN_ON(!pasync_handle); | 1686 | WARN_ON(!pasync_handle); |
1615 | 1687 | ||
1616 | pasync_handle->cri = | 1688 | pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID( |
1617 | BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid); | 1689 | beiscsi_conn->beiscsi_conn_cid); |
1618 | pasync_handle->is_header = is_header; | 1690 | pasync_handle->is_header = is_header; |
1619 | pasync_handle->buffer_len = dpl; | 1691 | pasync_handle->buffer_len = dpl; |
1620 | *pcq_index = index; | 1692 | *pcq_index = index; |
@@ -1674,18 +1746,13 @@ hwi_update_async_writables(struct beiscsi_hba *phba, | |||
1674 | } | 1746 | } |
1675 | 1747 | ||
1676 | static void hwi_free_async_msg(struct beiscsi_hba *phba, | 1748 | static void hwi_free_async_msg(struct beiscsi_hba *phba, |
1677 | unsigned int cri) | 1749 | struct hwi_async_pdu_context *pasync_ctx, |
1750 | unsigned int cri) | ||
1678 | { | 1751 | { |
1679 | struct hwi_controller *phwi_ctrlr; | ||
1680 | struct hwi_async_pdu_context *pasync_ctx; | ||
1681 | struct async_pdu_handle *pasync_handle, *tmp_handle; | 1752 | struct async_pdu_handle *pasync_handle, *tmp_handle; |
1682 | struct list_head *plist; | 1753 | struct list_head *plist; |
1683 | 1754 | ||
1684 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1685 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
1686 | |||
1687 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; | 1755 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; |
1688 | |||
1689 | list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { | 1756 | list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { |
1690 | list_del(&pasync_handle->link); | 1757 | list_del(&pasync_handle->link); |
1691 | 1758 | ||
@@ -1720,7 +1787,7 @@ hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx, | |||
1720 | } | 1787 | } |
1721 | 1788 | ||
1722 | static void hwi_post_async_buffers(struct beiscsi_hba *phba, | 1789 | static void hwi_post_async_buffers(struct beiscsi_hba *phba, |
1723 | unsigned int is_header) | 1790 | unsigned int is_header, uint8_t ulp_num) |
1724 | { | 1791 | { |
1725 | struct hwi_controller *phwi_ctrlr; | 1792 | struct hwi_controller *phwi_ctrlr; |
1726 | struct hwi_async_pdu_context *pasync_ctx; | 1793 | struct hwi_async_pdu_context *pasync_ctx; |
@@ -1728,13 +1795,13 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba, | |||
1728 | struct list_head *pfree_link, *pbusy_list; | 1795 | struct list_head *pfree_link, *pbusy_list; |
1729 | struct phys_addr *pasync_sge; | 1796 | struct phys_addr *pasync_sge; |
1730 | unsigned int ring_id, num_entries; | 1797 | unsigned int ring_id, num_entries; |
1731 | unsigned int host_write_num; | 1798 | unsigned int host_write_num, doorbell_offset; |
1732 | unsigned int writables; | 1799 | unsigned int writables; |
1733 | unsigned int i = 0; | 1800 | unsigned int i = 0; |
1734 | u32 doorbell = 0; | 1801 | u32 doorbell = 0; |
1735 | 1802 | ||
1736 | phwi_ctrlr = phba->phwi_ctrlr; | 1803 | phwi_ctrlr = phba->phwi_ctrlr; |
1737 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | 1804 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); |
1738 | num_entries = pasync_ctx->num_entries; | 1805 | num_entries = pasync_ctx->num_entries; |
1739 | 1806 | ||
1740 | if (is_header) { | 1807 | if (is_header) { |
@@ -1742,13 +1809,17 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba, | |||
1742 | pasync_ctx->async_header.free_entries); | 1809 | pasync_ctx->async_header.free_entries); |
1743 | pfree_link = pasync_ctx->async_header.free_list.next; | 1810 | pfree_link = pasync_ctx->async_header.free_list.next; |
1744 | host_write_num = pasync_ctx->async_header.host_write_ptr; | 1811 | host_write_num = pasync_ctx->async_header.host_write_ptr; |
1745 | ring_id = phwi_ctrlr->default_pdu_hdr.id; | 1812 | ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; |
1813 | doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. | ||
1814 | doorbell_offset; | ||
1746 | } else { | 1815 | } else { |
1747 | writables = min(pasync_ctx->async_data.writables, | 1816 | writables = min(pasync_ctx->async_data.writables, |
1748 | pasync_ctx->async_data.free_entries); | 1817 | pasync_ctx->async_data.free_entries); |
1749 | pfree_link = pasync_ctx->async_data.free_list.next; | 1818 | pfree_link = pasync_ctx->async_data.free_list.next; |
1750 | host_write_num = pasync_ctx->async_data.host_write_ptr; | 1819 | host_write_num = pasync_ctx->async_data.host_write_ptr; |
1751 | ring_id = phwi_ctrlr->default_pdu_data.id; | 1820 | ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; |
1821 | doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. | ||
1822 | doorbell_offset; | ||
1752 | } | 1823 | } |
1753 | 1824 | ||
1754 | writables = (writables / 8) * 8; | 1825 | writables = (writables / 8) * 8; |
@@ -1796,7 +1867,7 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba, | |||
1796 | doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK) | 1867 | doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK) |
1797 | << DB_DEF_PDU_CQPROC_SHIFT; | 1868 | << DB_DEF_PDU_CQPROC_SHIFT; |
1798 | 1869 | ||
1799 | iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET); | 1870 | iowrite32(doorbell, phba->db_va + doorbell_offset); |
1800 | } | 1871 | } |
1801 | } | 1872 | } |
1802 | 1873 | ||
@@ -1808,9 +1879,13 @@ static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba, | |||
1808 | struct hwi_async_pdu_context *pasync_ctx; | 1879 | struct hwi_async_pdu_context *pasync_ctx; |
1809 | struct async_pdu_handle *pasync_handle = NULL; | 1880 | struct async_pdu_handle *pasync_handle = NULL; |
1810 | unsigned int cq_index = -1; | 1881 | unsigned int cq_index = -1; |
1882 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
1883 | beiscsi_conn->beiscsi_conn_cid); | ||
1811 | 1884 | ||
1812 | phwi_ctrlr = phba->phwi_ctrlr; | 1885 | phwi_ctrlr = phba->phwi_ctrlr; |
1813 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | 1886 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, |
1887 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
1888 | cri_index)); | ||
1814 | 1889 | ||
1815 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | 1890 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, |
1816 | pdpdu_cqe, &cq_index); | 1891 | pdpdu_cqe, &cq_index); |
@@ -1819,8 +1894,10 @@ static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba, | |||
1819 | hwi_update_async_writables(phba, pasync_ctx, | 1894 | hwi_update_async_writables(phba, pasync_ctx, |
1820 | pasync_handle->is_header, cq_index); | 1895 | pasync_handle->is_header, cq_index); |
1821 | 1896 | ||
1822 | hwi_free_async_msg(phba, pasync_handle->cri); | 1897 | hwi_free_async_msg(phba, pasync_ctx, pasync_handle->cri); |
1823 | hwi_post_async_buffers(phba, pasync_handle->is_header); | 1898 | hwi_post_async_buffers(phba, pasync_handle->is_header, |
1899 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
1900 | cri_index)); | ||
1824 | } | 1901 | } |
1825 | 1902 | ||
1826 | static unsigned int | 1903 | static unsigned int |
@@ -1859,7 +1936,7 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, | |||
1859 | phdr, hdr_len, pfirst_buffer, | 1936 | phdr, hdr_len, pfirst_buffer, |
1860 | offset); | 1937 | offset); |
1861 | 1938 | ||
1862 | hwi_free_async_msg(phba, cri); | 1939 | hwi_free_async_msg(phba, pasync_ctx, cri); |
1863 | return 0; | 1940 | return 0; |
1864 | } | 1941 | } |
1865 | 1942 | ||
@@ -1875,13 +1952,16 @@ hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn, | |||
1875 | struct pdu_base *ppdu; | 1952 | struct pdu_base *ppdu; |
1876 | 1953 | ||
1877 | phwi_ctrlr = phba->phwi_ctrlr; | 1954 | phwi_ctrlr = phba->phwi_ctrlr; |
1878 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | 1955 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, |
1956 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
1957 | BE_GET_CRI_FROM_CID(beiscsi_conn-> | ||
1958 | beiscsi_conn_cid))); | ||
1879 | 1959 | ||
1880 | list_del(&pasync_handle->link); | 1960 | list_del(&pasync_handle->link); |
1881 | if (pasync_handle->is_header) { | 1961 | if (pasync_handle->is_header) { |
1882 | pasync_ctx->async_header.busy_entries--; | 1962 | pasync_ctx->async_header.busy_entries--; |
1883 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { | 1963 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { |
1884 | hwi_free_async_msg(phba, cri); | 1964 | hwi_free_async_msg(phba, pasync_ctx, cri); |
1885 | BUG(); | 1965 | BUG(); |
1886 | } | 1966 | } |
1887 | 1967 | ||
@@ -1936,9 +2016,14 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | |||
1936 | struct hwi_async_pdu_context *pasync_ctx; | 2016 | struct hwi_async_pdu_context *pasync_ctx; |
1937 | struct async_pdu_handle *pasync_handle = NULL; | 2017 | struct async_pdu_handle *pasync_handle = NULL; |
1938 | unsigned int cq_index = -1; | 2018 | unsigned int cq_index = -1; |
2019 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
2020 | beiscsi_conn->beiscsi_conn_cid); | ||
1939 | 2021 | ||
1940 | phwi_ctrlr = phba->phwi_ctrlr; | 2022 | phwi_ctrlr = phba->phwi_ctrlr; |
1941 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | 2023 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, |
2024 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
2025 | cri_index)); | ||
2026 | |||
1942 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | 2027 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, |
1943 | pdpdu_cqe, &cq_index); | 2028 | pdpdu_cqe, &cq_index); |
1944 | 2029 | ||
@@ -1947,7 +2032,9 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | |||
1947 | pasync_handle->is_header, cq_index); | 2032 | pasync_handle->is_header, cq_index); |
1948 | 2033 | ||
1949 | hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); | 2034 | hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); |
1950 | hwi_post_async_buffers(phba, pasync_handle->is_header); | 2035 | hwi_post_async_buffers(phba, pasync_handle->is_header, |
2036 | BEISCSI_GET_ULP_FROM_CRI( | ||
2037 | phwi_ctrlr, cri_index)); | ||
1951 | } | 2038 | } |
1952 | 2039 | ||
1953 | static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) | 2040 | static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) |
@@ -2072,8 +2159,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
2072 | "BM_%d : Received %s[%d] on CID : %d\n", | 2159 | "BM_%d : Received %s[%d] on CID : %d\n", |
2073 | cqe_desc[code], code, cid); | 2160 | cqe_desc[code], code, cid); |
2074 | 2161 | ||
2162 | spin_lock_bh(&phba->async_pdu_lock); | ||
2075 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | 2163 | hwi_process_default_pdu_ring(beiscsi_conn, phba, |
2076 | (struct i_t_dpdu_cqe *)sol); | 2164 | (struct i_t_dpdu_cqe *)sol); |
2165 | spin_unlock_bh(&phba->async_pdu_lock); | ||
2077 | break; | 2166 | break; |
2078 | case UNSOL_DATA_NOTIFY: | 2167 | case UNSOL_DATA_NOTIFY: |
2079 | beiscsi_log(phba, KERN_INFO, | 2168 | beiscsi_log(phba, KERN_INFO, |
@@ -2081,8 +2170,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
2081 | "BM_%d : Received %s[%d] on CID : %d\n", | 2170 | "BM_%d : Received %s[%d] on CID : %d\n", |
2082 | cqe_desc[code], code, cid); | 2171 | cqe_desc[code], code, cid); |
2083 | 2172 | ||
2173 | spin_lock_bh(&phba->async_pdu_lock); | ||
2084 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | 2174 | hwi_process_default_pdu_ring(beiscsi_conn, phba, |
2085 | (struct i_t_dpdu_cqe *)sol); | 2175 | (struct i_t_dpdu_cqe *)sol); |
2176 | spin_unlock_bh(&phba->async_pdu_lock); | ||
2086 | break; | 2177 | break; |
2087 | case CXN_INVALIDATE_INDEX_NOTIFY: | 2178 | case CXN_INVALIDATE_INDEX_NOTIFY: |
2088 | case CMD_INVALIDATED_NOTIFY: | 2179 | case CMD_INVALIDATED_NOTIFY: |
@@ -2110,8 +2201,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
2110 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | 2201 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, |
2111 | "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", | 2202 | "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", |
2112 | cqe_desc[code], code, cid); | 2203 | cqe_desc[code], code, cid); |
2204 | spin_lock_bh(&phba->async_pdu_lock); | ||
2113 | hwi_flush_default_pdu_buffer(phba, beiscsi_conn, | 2205 | hwi_flush_default_pdu_buffer(phba, beiscsi_conn, |
2114 | (struct i_t_dpdu_cqe *) sol); | 2206 | (struct i_t_dpdu_cqe *) sol); |
2207 | spin_unlock_bh(&phba->async_pdu_lock); | ||
2115 | break; | 2208 | break; |
2116 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: | 2209 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: |
2117 | case CXN_KILLED_BURST_LEN_MISMATCH: | 2210 | case CXN_KILLED_BURST_LEN_MISMATCH: |
@@ -2476,26 +2569,19 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) | |||
2476 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); | 2569 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); |
2477 | } | 2570 | } |
2478 | 2571 | ||
2572 | /** | ||
2573 | * beiscsi_find_mem_req()- Find mem needed | ||
2574 | * @phba: ptr to HBA struct | ||
2575 | **/ | ||
2479 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | 2576 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) |
2480 | { | 2577 | { |
2578 | uint8_t mem_descr_index, ulp_num; | ||
2481 | unsigned int num_cq_pages, num_async_pdu_buf_pages; | 2579 | unsigned int num_cq_pages, num_async_pdu_buf_pages; |
2482 | unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; | 2580 | unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; |
2483 | unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; | 2581 | unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; |
2484 | 2582 | ||
2485 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ | 2583 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ |
2486 | sizeof(struct sol_cqe)); | 2584 | sizeof(struct sol_cqe)); |
2487 | num_async_pdu_buf_pages = | ||
2488 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
2489 | phba->params.defpdu_hdr_sz); | ||
2490 | num_async_pdu_buf_sgl_pages = | ||
2491 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
2492 | sizeof(struct phys_addr)); | ||
2493 | num_async_pdu_data_pages = | ||
2494 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
2495 | phba->params.defpdu_data_sz); | ||
2496 | num_async_pdu_data_sgl_pages = | ||
2497 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
2498 | sizeof(struct phys_addr)); | ||
2499 | 2585 | ||
2500 | phba->params.hwi_ws_sz = sizeof(struct hwi_controller); | 2586 | phba->params.hwi_ws_sz = sizeof(struct hwi_controller); |
2501 | 2587 | ||
@@ -2517,24 +2603,79 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | |||
2517 | phba->params.icds_per_ctrl; | 2603 | phba->params.icds_per_ctrl; |
2518 | phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) * | 2604 | phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) * |
2519 | phba->params.num_sge_per_io * phba->params.icds_per_ctrl; | 2605 | phba->params.num_sge_per_io * phba->params.icds_per_ctrl; |
2520 | 2606 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | |
2521 | phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] = | 2607 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
2522 | num_async_pdu_buf_pages * PAGE_SIZE; | 2608 | |
2523 | phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] = | 2609 | num_async_pdu_buf_sgl_pages = |
2524 | num_async_pdu_data_pages * PAGE_SIZE; | 2610 | PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( |
2525 | phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] = | 2611 | phba, ulp_num) * |
2526 | num_async_pdu_buf_sgl_pages * PAGE_SIZE; | 2612 | sizeof(struct phys_addr)); |
2527 | phba->mem_req[HWI_MEM_ASYNC_DATA_RING] = | 2613 | |
2528 | num_async_pdu_data_sgl_pages * PAGE_SIZE; | 2614 | num_async_pdu_buf_pages = |
2529 | phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] = | 2615 | PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( |
2530 | phba->params.asyncpdus_per_ctrl * | 2616 | phba, ulp_num) * |
2531 | sizeof(struct async_pdu_handle); | 2617 | phba->params.defpdu_hdr_sz); |
2532 | phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] = | 2618 | |
2533 | phba->params.asyncpdus_per_ctrl * | 2619 | num_async_pdu_data_pages = |
2534 | sizeof(struct async_pdu_handle); | 2620 | PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( |
2535 | phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] = | 2621 | phba, ulp_num) * |
2536 | sizeof(struct hwi_async_pdu_context) + | 2622 | phba->params.defpdu_data_sz); |
2537 | (phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry)); | 2623 | |
2624 | num_async_pdu_data_sgl_pages = | ||
2625 | PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( | ||
2626 | phba, ulp_num) * | ||
2627 | sizeof(struct phys_addr)); | ||
2628 | |||
2629 | mem_descr_index = (HWI_MEM_TEMPLATE_HDR_ULP0 + | ||
2630 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2631 | phba->mem_req[mem_descr_index] = | ||
2632 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | ||
2633 | BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE; | ||
2634 | |||
2635 | mem_descr_index = (HWI_MEM_ASYNC_HEADER_BUF_ULP0 + | ||
2636 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2637 | phba->mem_req[mem_descr_index] = | ||
2638 | num_async_pdu_buf_pages * | ||
2639 | PAGE_SIZE; | ||
2640 | |||
2641 | mem_descr_index = (HWI_MEM_ASYNC_DATA_BUF_ULP0 + | ||
2642 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2643 | phba->mem_req[mem_descr_index] = | ||
2644 | num_async_pdu_data_pages * | ||
2645 | PAGE_SIZE; | ||
2646 | |||
2647 | mem_descr_index = (HWI_MEM_ASYNC_HEADER_RING_ULP0 + | ||
2648 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2649 | phba->mem_req[mem_descr_index] = | ||
2650 | num_async_pdu_buf_sgl_pages * | ||
2651 | PAGE_SIZE; | ||
2652 | |||
2653 | mem_descr_index = (HWI_MEM_ASYNC_DATA_RING_ULP0 + | ||
2654 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2655 | phba->mem_req[mem_descr_index] = | ||
2656 | num_async_pdu_data_sgl_pages * | ||
2657 | PAGE_SIZE; | ||
2658 | |||
2659 | mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + | ||
2660 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2661 | phba->mem_req[mem_descr_index] = | ||
2662 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | ||
2663 | sizeof(struct async_pdu_handle); | ||
2664 | |||
2665 | mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + | ||
2666 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2667 | phba->mem_req[mem_descr_index] = | ||
2668 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | ||
2669 | sizeof(struct async_pdu_handle); | ||
2670 | |||
2671 | mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + | ||
2672 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2673 | phba->mem_req[mem_descr_index] = | ||
2674 | sizeof(struct hwi_async_pdu_context) + | ||
2675 | (BEISCSI_GET_CID_COUNT(phba, ulp_num) * | ||
2676 | sizeof(struct hwi_async_entry)); | ||
2677 | } | ||
2678 | } | ||
2538 | } | 2679 | } |
2539 | 2680 | ||
2540 | static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | 2681 | static int beiscsi_alloc_mem(struct beiscsi_hba *phba) |
@@ -2576,6 +2717,12 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | |||
2576 | 2717 | ||
2577 | mem_descr = phba->init_mem; | 2718 | mem_descr = phba->init_mem; |
2578 | for (i = 0; i < SE_MEM_MAX; i++) { | 2719 | for (i = 0; i < SE_MEM_MAX; i++) { |
2720 | if (!phba->mem_req[i]) { | ||
2721 | mem_descr->mem_array = NULL; | ||
2722 | mem_descr++; | ||
2723 | continue; | ||
2724 | } | ||
2725 | |||
2579 | j = 0; | 2726 | j = 0; |
2580 | mem_arr = mem_arr_orig; | 2727 | mem_arr = mem_arr_orig; |
2581 | alloc_size = phba->mem_req[i]; | 2728 | alloc_size = phba->mem_req[i]; |
@@ -2697,7 +2844,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
2697 | /* Allocate memory for WRBQ */ | 2844 | /* Allocate memory for WRBQ */ |
2698 | phwi_ctxt = phwi_ctrlr->phwi_ctxt; | 2845 | phwi_ctxt = phwi_ctrlr->phwi_ctxt; |
2699 | phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * | 2846 | phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * |
2700 | phba->fw_config.iscsi_cid_count, | 2847 | phba->params.cxns_per_ctrl, |
2701 | GFP_KERNEL); | 2848 | GFP_KERNEL); |
2702 | if (!phwi_ctxt->be_wrbq) { | 2849 | if (!phwi_ctxt->be_wrbq) { |
2703 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 2850 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
@@ -2779,6 +2926,7 @@ init_wrb_hndl_failed: | |||
2779 | 2926 | ||
2780 | static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | 2927 | static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) |
2781 | { | 2928 | { |
2929 | uint8_t ulp_num; | ||
2782 | struct hwi_controller *phwi_ctrlr; | 2930 | struct hwi_controller *phwi_ctrlr; |
2783 | struct hba_parameters *p = &phba->params; | 2931 | struct hba_parameters *p = &phba->params; |
2784 | struct hwi_async_pdu_context *pasync_ctx; | 2932 | struct hwi_async_pdu_context *pasync_ctx; |
@@ -2786,155 +2934,150 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | |||
2786 | unsigned int index, idx, num_per_mem, num_async_data; | 2934 | unsigned int index, idx, num_per_mem, num_async_data; |
2787 | struct be_mem_descriptor *mem_descr; | 2935 | struct be_mem_descriptor *mem_descr; |
2788 | 2936 | ||
2789 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2937 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
2790 | mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT; | 2938 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
2791 | 2939 | ||
2792 | phwi_ctrlr = phba->phwi_ctrlr; | 2940 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
2793 | phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *) | 2941 | mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
2942 | (ulp_num * MEM_DESCR_OFFSET)); | ||
2943 | |||
2944 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2945 | phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = | ||
2946 | (struct hwi_async_pdu_context *) | ||
2947 | mem_descr->mem_array[0].virtual_address; | ||
2948 | |||
2949 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | ||
2950 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); | ||
2951 | |||
2952 | pasync_ctx->async_entry = | ||
2953 | (struct hwi_async_entry *) | ||
2954 | ((long unsigned int)pasync_ctx + | ||
2955 | sizeof(struct hwi_async_pdu_context)); | ||
2956 | |||
2957 | pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, | ||
2958 | ulp_num); | ||
2959 | pasync_ctx->buffer_size = p->defpdu_hdr_sz; | ||
2960 | |||
2961 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2962 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + | ||
2963 | (ulp_num * MEM_DESCR_OFFSET); | ||
2964 | if (mem_descr->mem_array[0].virtual_address) { | ||
2965 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2966 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2967 | " HWI_MEM_ASYNC_HEADER_BUF_ULP%d va=%p\n", | ||
2968 | ulp_num, | ||
2969 | mem_descr->mem_array[0]. | ||
2970 | virtual_address); | ||
2971 | } else | ||
2972 | beiscsi_log(phba, KERN_WARNING, | ||
2973 | BEISCSI_LOG_INIT, | ||
2974 | "BM_%d : No Virtual address for ULP : %d\n", | ||
2975 | ulp_num); | ||
2976 | |||
2977 | pasync_ctx->async_header.va_base = | ||
2794 | mem_descr->mem_array[0].virtual_address; | 2978 | mem_descr->mem_array[0].virtual_address; |
2795 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; | ||
2796 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); | ||
2797 | 2979 | ||
2798 | pasync_ctx->async_entry = kzalloc(sizeof(struct hwi_async_entry) * | 2980 | pasync_ctx->async_header.pa_base.u.a64.address = |
2799 | phba->fw_config.iscsi_cid_count, | 2981 | mem_descr->mem_array[0]. |
2800 | GFP_KERNEL); | 2982 | bus_address.u.a64.address; |
2801 | if (!pasync_ctx->async_entry) { | ||
2802 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
2803 | "BM_%d : hwi_init_async_pdu_ctx Mem Alloc Failed\n"); | ||
2804 | return -ENOMEM; | ||
2805 | } | ||
2806 | |||
2807 | pasync_ctx->num_entries = p->asyncpdus_per_ctrl; | ||
2808 | pasync_ctx->buffer_size = p->defpdu_hdr_sz; | ||
2809 | |||
2810 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2811 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF; | ||
2812 | if (mem_descr->mem_array[0].virtual_address) { | ||
2813 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2814 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2815 | " HWI_MEM_ASYNC_HEADER_BUF va=%p\n", | ||
2816 | mem_descr->mem_array[0].virtual_address); | ||
2817 | } else | ||
2818 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2819 | "BM_%d : No Virtual address\n"); | ||
2820 | |||
2821 | pasync_ctx->async_header.va_base = | ||
2822 | mem_descr->mem_array[0].virtual_address; | ||
2823 | |||
2824 | pasync_ctx->async_header.pa_base.u.a64.address = | ||
2825 | mem_descr->mem_array[0].bus_address.u.a64.address; | ||
2826 | |||
2827 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2828 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; | ||
2829 | if (mem_descr->mem_array[0].virtual_address) { | ||
2830 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2831 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2832 | " HWI_MEM_ASYNC_HEADER_RING va=%p\n", | ||
2833 | mem_descr->mem_array[0].virtual_address); | ||
2834 | } else | ||
2835 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2836 | "BM_%d : No Virtual address\n"); | ||
2837 | |||
2838 | pasync_ctx->async_header.ring_base = | ||
2839 | mem_descr->mem_array[0].virtual_address; | ||
2840 | |||
2841 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2842 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE; | ||
2843 | if (mem_descr->mem_array[0].virtual_address) { | ||
2844 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2845 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2846 | " HWI_MEM_ASYNC_HEADER_HANDLE va=%p\n", | ||
2847 | mem_descr->mem_array[0].virtual_address); | ||
2848 | } else | ||
2849 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2850 | "BM_%d : No Virtual address\n"); | ||
2851 | |||
2852 | pasync_ctx->async_header.handle_base = | ||
2853 | mem_descr->mem_array[0].virtual_address; | ||
2854 | pasync_ctx->async_header.writables = 0; | ||
2855 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); | ||
2856 | |||
2857 | |||
2858 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2859 | mem_descr += HWI_MEM_ASYNC_DATA_RING; | ||
2860 | if (mem_descr->mem_array[0].virtual_address) { | ||
2861 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2862 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2863 | " HWI_MEM_ASYNC_DATA_RING va=%p\n", | ||
2864 | mem_descr->mem_array[0].virtual_address); | ||
2865 | } else | ||
2866 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2867 | "BM_%d : No Virtual address\n"); | ||
2868 | |||
2869 | pasync_ctx->async_data.ring_base = | ||
2870 | mem_descr->mem_array[0].virtual_address; | ||
2871 | |||
2872 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
2873 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE; | ||
2874 | if (!mem_descr->mem_array[0].virtual_address) | ||
2875 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2876 | "BM_%d : No Virtual address\n"); | ||
2877 | 2983 | ||
2878 | pasync_ctx->async_data.handle_base = | 2984 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
2879 | mem_descr->mem_array[0].virtual_address; | 2985 | mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + |
2880 | pasync_ctx->async_data.writables = 0; | 2986 | (ulp_num * MEM_DESCR_OFFSET); |
2881 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); | 2987 | if (mem_descr->mem_array[0].virtual_address) { |
2988 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
2989 | "BM_%d : hwi_init_async_pdu_ctx" | ||
2990 | " HWI_MEM_ASYNC_HEADER_RING_ULP%d va=%p\n", | ||
2991 | ulp_num, | ||
2992 | mem_descr->mem_array[0]. | ||
2993 | virtual_address); | ||
2994 | } else | ||
2995 | beiscsi_log(phba, KERN_WARNING, | ||
2996 | BEISCSI_LOG_INIT, | ||
2997 | "BM_%d : No Virtual address for ULP : %d\n", | ||
2998 | ulp_num); | ||
2999 | |||
3000 | pasync_ctx->async_header.ring_base = | ||
3001 | mem_descr->mem_array[0].virtual_address; | ||
2882 | 3002 | ||
2883 | pasync_header_h = | 3003 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
2884 | (struct async_pdu_handle *)pasync_ctx->async_header.handle_base; | 3004 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + |
2885 | pasync_data_h = | 3005 | (ulp_num * MEM_DESCR_OFFSET); |
2886 | (struct async_pdu_handle *)pasync_ctx->async_data.handle_base; | 3006 | if (mem_descr->mem_array[0].virtual_address) { |
3007 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
3008 | "BM_%d : hwi_init_async_pdu_ctx" | ||
3009 | " HWI_MEM_ASYNC_HEADER_HANDLE_ULP%d va=%p\n", | ||
3010 | ulp_num, | ||
3011 | mem_descr->mem_array[0]. | ||
3012 | virtual_address); | ||
3013 | } else | ||
3014 | beiscsi_log(phba, KERN_WARNING, | ||
3015 | BEISCSI_LOG_INIT, | ||
3016 | "BM_%d : No Virtual address for ULP : %d\n", | ||
3017 | ulp_num); | ||
3018 | |||
3019 | pasync_ctx->async_header.handle_base = | ||
3020 | mem_descr->mem_array[0].virtual_address; | ||
3021 | pasync_ctx->async_header.writables = 0; | ||
3022 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); | ||
3023 | |||
3024 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
3025 | mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + | ||
3026 | (ulp_num * MEM_DESCR_OFFSET); | ||
3027 | if (mem_descr->mem_array[0].virtual_address) { | ||
3028 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
3029 | "BM_%d : hwi_init_async_pdu_ctx" | ||
3030 | " HWI_MEM_ASYNC_DATA_RING_ULP%d va=%p\n", | ||
3031 | ulp_num, | ||
3032 | mem_descr->mem_array[0]. | ||
3033 | virtual_address); | ||
3034 | } else | ||
3035 | beiscsi_log(phba, KERN_WARNING, | ||
3036 | BEISCSI_LOG_INIT, | ||
3037 | "BM_%d : No Virtual address for ULP : %d\n", | ||
3038 | ulp_num); | ||
3039 | |||
3040 | pasync_ctx->async_data.ring_base = | ||
3041 | mem_descr->mem_array[0].virtual_address; | ||
2887 | 3042 | ||
2888 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 3043 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
2889 | mem_descr += HWI_MEM_ASYNC_DATA_BUF; | 3044 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + |
2890 | if (mem_descr->mem_array[0].virtual_address) { | 3045 | (ulp_num * MEM_DESCR_OFFSET); |
2891 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 3046 | if (!mem_descr->mem_array[0].virtual_address) |
2892 | "BM_%d : hwi_init_async_pdu_ctx" | 3047 | beiscsi_log(phba, KERN_WARNING, |
2893 | " HWI_MEM_ASYNC_DATA_BUF va=%p\n", | 3048 | BEISCSI_LOG_INIT, |
2894 | mem_descr->mem_array[0].virtual_address); | 3049 | "BM_%d : No Virtual address for ULP : %d\n", |
2895 | } else | 3050 | ulp_num); |
2896 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
2897 | "BM_%d : No Virtual address\n"); | ||
2898 | 3051 | ||
2899 | idx = 0; | 3052 | pasync_ctx->async_data.handle_base = |
2900 | pasync_ctx->async_data.va_base = | 3053 | mem_descr->mem_array[0].virtual_address; |
2901 | mem_descr->mem_array[idx].virtual_address; | 3054 | pasync_ctx->async_data.writables = 0; |
2902 | pasync_ctx->async_data.pa_base.u.a64.address = | 3055 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); |
2903 | mem_descr->mem_array[idx].bus_address.u.a64.address; | 3056 | |
2904 | 3057 | pasync_header_h = | |
2905 | num_async_data = ((mem_descr->mem_array[idx].size) / | 3058 | (struct async_pdu_handle *) |
2906 | phba->params.defpdu_data_sz); | 3059 | pasync_ctx->async_header.handle_base; |
2907 | num_per_mem = 0; | 3060 | pasync_data_h = |
2908 | 3061 | (struct async_pdu_handle *) | |
2909 | for (index = 0; index < p->asyncpdus_per_ctrl; index++) { | 3062 | pasync_ctx->async_data.handle_base; |
2910 | pasync_header_h->cri = -1; | 3063 | |
2911 | pasync_header_h->index = (char)index; | 3064 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
2912 | INIT_LIST_HEAD(&pasync_header_h->link); | 3065 | mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + |
2913 | pasync_header_h->pbuffer = | 3066 | (ulp_num * MEM_DESCR_OFFSET); |
2914 | (void *)((unsigned long) | 3067 | if (mem_descr->mem_array[0].virtual_address) { |
2915 | (pasync_ctx->async_header.va_base) + | 3068 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
2916 | (p->defpdu_hdr_sz * index)); | 3069 | "BM_%d : hwi_init_async_pdu_ctx" |
2917 | 3070 | " HWI_MEM_ASYNC_DATA_BUF_ULP%d va=%p\n", | |
2918 | pasync_header_h->pa.u.a64.address = | 3071 | ulp_num, |
2919 | pasync_ctx->async_header.pa_base.u.a64.address + | 3072 | mem_descr->mem_array[0]. |
2920 | (p->defpdu_hdr_sz * index); | 3073 | virtual_address); |
2921 | 3074 | } else | |
2922 | list_add_tail(&pasync_header_h->link, | 3075 | beiscsi_log(phba, KERN_WARNING, |
2923 | &pasync_ctx->async_header.free_list); | 3076 | BEISCSI_LOG_INIT, |
2924 | pasync_header_h++; | 3077 | "BM_%d : No Virtual address for ULP : %d\n", |
2925 | pasync_ctx->async_header.free_entries++; | 3078 | ulp_num); |
2926 | pasync_ctx->async_header.writables++; | 3079 | |
2927 | 3080 | idx = 0; | |
2928 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list); | ||
2929 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
2930 | header_busy_list); | ||
2931 | pasync_data_h->cri = -1; | ||
2932 | pasync_data_h->index = (char)index; | ||
2933 | INIT_LIST_HEAD(&pasync_data_h->link); | ||
2934 | |||
2935 | if (!num_async_data) { | ||
2936 | num_per_mem = 0; | ||
2937 | idx++; | ||
2938 | pasync_ctx->async_data.va_base = | 3081 | pasync_ctx->async_data.va_base = |
2939 | mem_descr->mem_array[idx].virtual_address; | 3082 | mem_descr->mem_array[idx].virtual_address; |
2940 | pasync_ctx->async_data.pa_base.u.a64.address = | 3083 | pasync_ctx->async_data.pa_base.u.a64.address = |
@@ -2943,32 +3086,83 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | |||
2943 | 3086 | ||
2944 | num_async_data = ((mem_descr->mem_array[idx].size) / | 3087 | num_async_data = ((mem_descr->mem_array[idx].size) / |
2945 | phba->params.defpdu_data_sz); | 3088 | phba->params.defpdu_data_sz); |
2946 | } | 3089 | num_per_mem = 0; |
2947 | pasync_data_h->pbuffer = | ||
2948 | (void *)((unsigned long) | ||
2949 | (pasync_ctx->async_data.va_base) + | ||
2950 | (p->defpdu_data_sz * num_per_mem)); | ||
2951 | |||
2952 | pasync_data_h->pa.u.a64.address = | ||
2953 | pasync_ctx->async_data.pa_base.u.a64.address + | ||
2954 | (p->defpdu_data_sz * num_per_mem); | ||
2955 | num_per_mem++; | ||
2956 | num_async_data--; | ||
2957 | 3090 | ||
2958 | list_add_tail(&pasync_data_h->link, | 3091 | for (index = 0; index < BEISCSI_GET_CID_COUNT |
2959 | &pasync_ctx->async_data.free_list); | 3092 | (phba, ulp_num); index++) { |
2960 | pasync_data_h++; | 3093 | pasync_header_h->cri = -1; |
2961 | pasync_ctx->async_data.free_entries++; | 3094 | pasync_header_h->index = (char)index; |
2962 | pasync_ctx->async_data.writables++; | 3095 | INIT_LIST_HEAD(&pasync_header_h->link); |
3096 | pasync_header_h->pbuffer = | ||
3097 | (void *)((unsigned long) | ||
3098 | (pasync_ctx-> | ||
3099 | async_header.va_base) + | ||
3100 | (p->defpdu_hdr_sz * index)); | ||
3101 | |||
3102 | pasync_header_h->pa.u.a64.address = | ||
3103 | pasync_ctx->async_header.pa_base.u.a64. | ||
3104 | address + (p->defpdu_hdr_sz * index); | ||
3105 | |||
3106 | list_add_tail(&pasync_header_h->link, | ||
3107 | &pasync_ctx->async_header. | ||
3108 | free_list); | ||
3109 | pasync_header_h++; | ||
3110 | pasync_ctx->async_header.free_entries++; | ||
3111 | pasync_ctx->async_header.writables++; | ||
3112 | |||
3113 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
3114 | wait_queue.list); | ||
3115 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
3116 | header_busy_list); | ||
3117 | pasync_data_h->cri = -1; | ||
3118 | pasync_data_h->index = (char)index; | ||
3119 | INIT_LIST_HEAD(&pasync_data_h->link); | ||
3120 | |||
3121 | if (!num_async_data) { | ||
3122 | num_per_mem = 0; | ||
3123 | idx++; | ||
3124 | pasync_ctx->async_data.va_base = | ||
3125 | mem_descr->mem_array[idx]. | ||
3126 | virtual_address; | ||
3127 | pasync_ctx->async_data.pa_base.u. | ||
3128 | a64.address = | ||
3129 | mem_descr->mem_array[idx]. | ||
3130 | bus_address.u.a64.address; | ||
3131 | num_async_data = | ||
3132 | ((mem_descr->mem_array[idx]. | ||
3133 | size) / | ||
3134 | phba->params.defpdu_data_sz); | ||
3135 | } | ||
3136 | pasync_data_h->pbuffer = | ||
3137 | (void *)((unsigned long) | ||
3138 | (pasync_ctx->async_data.va_base) + | ||
3139 | (p->defpdu_data_sz * num_per_mem)); | ||
3140 | |||
3141 | pasync_data_h->pa.u.a64.address = | ||
3142 | pasync_ctx->async_data.pa_base.u.a64. | ||
3143 | address + (p->defpdu_data_sz * | ||
3144 | num_per_mem); | ||
3145 | num_per_mem++; | ||
3146 | num_async_data--; | ||
3147 | |||
3148 | list_add_tail(&pasync_data_h->link, | ||
3149 | &pasync_ctx->async_data. | ||
3150 | free_list); | ||
3151 | pasync_data_h++; | ||
3152 | pasync_ctx->async_data.free_entries++; | ||
3153 | pasync_ctx->async_data.writables++; | ||
3154 | |||
3155 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
3156 | data_busy_list); | ||
3157 | } | ||
2963 | 3158 | ||
2964 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list); | 3159 | pasync_ctx->async_header.host_write_ptr = 0; |
3160 | pasync_ctx->async_header.ep_read_ptr = -1; | ||
3161 | pasync_ctx->async_data.host_write_ptr = 0; | ||
3162 | pasync_ctx->async_data.ep_read_ptr = -1; | ||
3163 | } | ||
2965 | } | 3164 | } |
2966 | 3165 | ||
2967 | pasync_ctx->async_header.host_write_ptr = 0; | ||
2968 | pasync_ctx->async_header.ep_read_ptr = -1; | ||
2969 | pasync_ctx->async_data.host_write_ptr = 0; | ||
2970 | pasync_ctx->async_data.ep_read_ptr = -1; | ||
2971 | |||
2972 | return 0; | 3166 | return 0; |
2973 | } | 3167 | } |
2974 | 3168 | ||
@@ -3164,7 +3358,7 @@ static int | |||
3164 | beiscsi_create_def_hdr(struct beiscsi_hba *phba, | 3358 | beiscsi_create_def_hdr(struct beiscsi_hba *phba, |
3165 | struct hwi_context_memory *phwi_context, | 3359 | struct hwi_context_memory *phwi_context, |
3166 | struct hwi_controller *phwi_ctrlr, | 3360 | struct hwi_controller *phwi_ctrlr, |
3167 | unsigned int def_pdu_ring_sz) | 3361 | unsigned int def_pdu_ring_sz, uint8_t ulp_num) |
3168 | { | 3362 | { |
3169 | unsigned int idx; | 3363 | unsigned int idx; |
3170 | int ret; | 3364 | int ret; |
@@ -3174,36 +3368,42 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba, | |||
3174 | void *dq_vaddress; | 3368 | void *dq_vaddress; |
3175 | 3369 | ||
3176 | idx = 0; | 3370 | idx = 0; |
3177 | dq = &phwi_context->be_def_hdrq; | 3371 | dq = &phwi_context->be_def_hdrq[ulp_num]; |
3178 | cq = &phwi_context->be_cq[0]; | 3372 | cq = &phwi_context->be_cq[0]; |
3179 | mem = &dq->dma_mem; | 3373 | mem = &dq->dma_mem; |
3180 | mem_descr = phba->init_mem; | 3374 | mem_descr = phba->init_mem; |
3181 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; | 3375 | mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + |
3376 | (ulp_num * MEM_DESCR_OFFSET); | ||
3182 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; | 3377 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; |
3183 | ret = be_fill_queue(dq, mem_descr->mem_array[0].size / | 3378 | ret = be_fill_queue(dq, mem_descr->mem_array[0].size / |
3184 | sizeof(struct phys_addr), | 3379 | sizeof(struct phys_addr), |
3185 | sizeof(struct phys_addr), dq_vaddress); | 3380 | sizeof(struct phys_addr), dq_vaddress); |
3186 | if (ret) { | 3381 | if (ret) { |
3187 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3382 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3188 | "BM_%d : be_fill_queue Failed for DEF PDU HDR\n"); | 3383 | "BM_%d : be_fill_queue Failed for DEF PDU HDR on ULP : %d\n", |
3384 | ulp_num); | ||
3385 | |||
3189 | return ret; | 3386 | return ret; |
3190 | } | 3387 | } |
3191 | mem->dma = (unsigned long)mem_descr->mem_array[idx]. | 3388 | mem->dma = (unsigned long)mem_descr->mem_array[idx]. |
3192 | bus_address.u.a64.address; | 3389 | bus_address.u.a64.address; |
3193 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq, | 3390 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq, |
3194 | def_pdu_ring_sz, | 3391 | def_pdu_ring_sz, |
3195 | phba->params.defpdu_hdr_sz); | 3392 | phba->params.defpdu_hdr_sz, |
3393 | BEISCSI_DEFQ_HDR, ulp_num); | ||
3196 | if (ret) { | 3394 | if (ret) { |
3197 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3395 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3198 | "BM_%d : be_cmd_create_default_pdu_queue Failed DEFHDR\n"); | 3396 | "BM_%d : be_cmd_create_default_pdu_queue Failed DEFHDR on ULP : %d\n", |
3397 | ulp_num); | ||
3398 | |||
3199 | return ret; | 3399 | return ret; |
3200 | } | 3400 | } |
3201 | phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id; | ||
3202 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
3203 | "BM_%d : iscsi def pdu id is %d\n", | ||
3204 | phwi_context->be_def_hdrq.id); | ||
3205 | 3401 | ||
3206 | hwi_post_async_buffers(phba, 1); | 3402 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
3403 | "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", | ||
3404 | ulp_num, | ||
3405 | phwi_context->be_def_hdrq[ulp_num].id); | ||
3406 | hwi_post_async_buffers(phba, BEISCSI_DEFQ_HDR, ulp_num); | ||
3207 | return 0; | 3407 | return 0; |
3208 | } | 3408 | } |
3209 | 3409 | ||
@@ -3211,7 +3411,7 @@ static int | |||
3211 | beiscsi_create_def_data(struct beiscsi_hba *phba, | 3411 | beiscsi_create_def_data(struct beiscsi_hba *phba, |
3212 | struct hwi_context_memory *phwi_context, | 3412 | struct hwi_context_memory *phwi_context, |
3213 | struct hwi_controller *phwi_ctrlr, | 3413 | struct hwi_controller *phwi_ctrlr, |
3214 | unsigned int def_pdu_ring_sz) | 3414 | unsigned int def_pdu_ring_sz, uint8_t ulp_num) |
3215 | { | 3415 | { |
3216 | unsigned int idx; | 3416 | unsigned int idx; |
3217 | int ret; | 3417 | int ret; |
@@ -3221,43 +3421,86 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, | |||
3221 | void *dq_vaddress; | 3421 | void *dq_vaddress; |
3222 | 3422 | ||
3223 | idx = 0; | 3423 | idx = 0; |
3224 | dataq = &phwi_context->be_def_dataq; | 3424 | dataq = &phwi_context->be_def_dataq[ulp_num]; |
3225 | cq = &phwi_context->be_cq[0]; | 3425 | cq = &phwi_context->be_cq[0]; |
3226 | mem = &dataq->dma_mem; | 3426 | mem = &dataq->dma_mem; |
3227 | mem_descr = phba->init_mem; | 3427 | mem_descr = phba->init_mem; |
3228 | mem_descr += HWI_MEM_ASYNC_DATA_RING; | 3428 | mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + |
3429 | (ulp_num * MEM_DESCR_OFFSET); | ||
3229 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; | 3430 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; |
3230 | ret = be_fill_queue(dataq, mem_descr->mem_array[0].size / | 3431 | ret = be_fill_queue(dataq, mem_descr->mem_array[0].size / |
3231 | sizeof(struct phys_addr), | 3432 | sizeof(struct phys_addr), |
3232 | sizeof(struct phys_addr), dq_vaddress); | 3433 | sizeof(struct phys_addr), dq_vaddress); |
3233 | if (ret) { | 3434 | if (ret) { |
3234 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3435 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3235 | "BM_%d : be_fill_queue Failed for DEF PDU DATA\n"); | 3436 | "BM_%d : be_fill_queue Failed for DEF PDU " |
3437 | "DATA on ULP : %d\n", | ||
3438 | ulp_num); | ||
3439 | |||
3236 | return ret; | 3440 | return ret; |
3237 | } | 3441 | } |
3238 | mem->dma = (unsigned long)mem_descr->mem_array[idx]. | 3442 | mem->dma = (unsigned long)mem_descr->mem_array[idx]. |
3239 | bus_address.u.a64.address; | 3443 | bus_address.u.a64.address; |
3240 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq, | 3444 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq, |
3241 | def_pdu_ring_sz, | 3445 | def_pdu_ring_sz, |
3242 | phba->params.defpdu_data_sz); | 3446 | phba->params.defpdu_data_sz, |
3447 | BEISCSI_DEFQ_DATA, ulp_num); | ||
3243 | if (ret) { | 3448 | if (ret) { |
3244 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3449 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3245 | "BM_%d be_cmd_create_default_pdu_queue" | 3450 | "BM_%d be_cmd_create_default_pdu_queue" |
3246 | " Failed for DEF PDU DATA\n"); | 3451 | " Failed for DEF PDU DATA on ULP : %d\n", |
3452 | ulp_num); | ||
3247 | return ret; | 3453 | return ret; |
3248 | } | 3454 | } |
3249 | phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id; | 3455 | |
3250 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 3456 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
3251 | "BM_%d : iscsi def data id is %d\n", | 3457 | "BM_%d : iscsi def data id on ULP : %d is %d\n", |
3252 | phwi_context->be_def_dataq.id); | 3458 | ulp_num, |
3459 | phwi_context->be_def_dataq[ulp_num].id); | ||
3253 | 3460 | ||
3254 | hwi_post_async_buffers(phba, 0); | 3461 | hwi_post_async_buffers(phba, BEISCSI_DEFQ_DATA, ulp_num); |
3255 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 3462 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
3256 | "BM_%d : DEFAULT PDU DATA RING CREATED\n"); | 3463 | "BM_%d : DEFAULT PDU DATA RING CREATED" |
3464 | "on ULP : %d\n", ulp_num); | ||
3257 | 3465 | ||
3258 | return 0; | 3466 | return 0; |
3259 | } | 3467 | } |
3260 | 3468 | ||
3469 | |||
3470 | static int | ||
3471 | beiscsi_post_template_hdr(struct beiscsi_hba *phba) | ||
3472 | { | ||
3473 | struct be_mem_descriptor *mem_descr; | ||
3474 | struct mem_array *pm_arr; | ||
3475 | struct be_dma_mem sgl; | ||
3476 | int status, ulp_num; | ||
3477 | |||
3478 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
3479 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
3480 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
3481 | mem_descr += HWI_MEM_TEMPLATE_HDR_ULP0 + | ||
3482 | (ulp_num * MEM_DESCR_OFFSET); | ||
3483 | pm_arr = mem_descr->mem_array; | ||
3484 | |||
3485 | hwi_build_be_sgl_arr(phba, pm_arr, &sgl); | ||
3486 | status = be_cmd_iscsi_post_template_hdr( | ||
3487 | &phba->ctrl, &sgl); | ||
3488 | |||
3489 | if (status != 0) { | ||
3490 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
3491 | "BM_%d : Post Template HDR Failed for" | ||
3492 | "ULP_%d\n", ulp_num); | ||
3493 | return status; | ||
3494 | } | ||
3495 | |||
3496 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
3497 | "BM_%d : Template HDR Pages Posted for" | ||
3498 | "ULP_%d\n", ulp_num); | ||
3499 | } | ||
3500 | } | ||
3501 | return 0; | ||
3502 | } | ||
3503 | |||
3261 | static int | 3504 | static int |
3262 | beiscsi_post_pages(struct beiscsi_hba *phba) | 3505 | beiscsi_post_pages(struct beiscsi_hba *phba) |
3263 | { | 3506 | { |
@@ -3265,14 +3508,18 @@ beiscsi_post_pages(struct beiscsi_hba *phba) | |||
3265 | struct mem_array *pm_arr; | 3508 | struct mem_array *pm_arr; |
3266 | unsigned int page_offset, i; | 3509 | unsigned int page_offset, i; |
3267 | struct be_dma_mem sgl; | 3510 | struct be_dma_mem sgl; |
3268 | int status; | 3511 | int status, ulp_num = 0; |
3269 | 3512 | ||
3270 | mem_descr = phba->init_mem; | 3513 | mem_descr = phba->init_mem; |
3271 | mem_descr += HWI_MEM_SGE; | 3514 | mem_descr += HWI_MEM_SGE; |
3272 | pm_arr = mem_descr->mem_array; | 3515 | pm_arr = mem_descr->mem_array; |
3273 | 3516 | ||
3517 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
3518 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) | ||
3519 | break; | ||
3520 | |||
3274 | page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io * | 3521 | page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io * |
3275 | phba->fw_config.iscsi_icd_start) / PAGE_SIZE; | 3522 | phba->fw_config.iscsi_icd_start[ulp_num]) / PAGE_SIZE; |
3276 | for (i = 0; i < mem_descr->num_elements; i++) { | 3523 | for (i = 0; i < mem_descr->num_elements; i++) { |
3277 | hwi_build_be_sgl_arr(phba, pm_arr, &sgl); | 3524 | hwi_build_be_sgl_arr(phba, pm_arr, &sgl); |
3278 | status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl, | 3525 | status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl, |
@@ -3324,13 +3571,15 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
3324 | { | 3571 | { |
3325 | unsigned int wrb_mem_index, offset, size, num_wrb_rings; | 3572 | unsigned int wrb_mem_index, offset, size, num_wrb_rings; |
3326 | u64 pa_addr_lo; | 3573 | u64 pa_addr_lo; |
3327 | unsigned int idx, num, i; | 3574 | unsigned int idx, num, i, ulp_num; |
3328 | struct mem_array *pwrb_arr; | 3575 | struct mem_array *pwrb_arr; |
3329 | void *wrb_vaddr; | 3576 | void *wrb_vaddr; |
3330 | struct be_dma_mem sgl; | 3577 | struct be_dma_mem sgl; |
3331 | struct be_mem_descriptor *mem_descr; | 3578 | struct be_mem_descriptor *mem_descr; |
3332 | struct hwi_wrb_context *pwrb_context; | 3579 | struct hwi_wrb_context *pwrb_context; |
3333 | int status; | 3580 | int status; |
3581 | uint8_t ulp_count = 0, ulp_base_num = 0; | ||
3582 | uint16_t cid_count_ulp[BEISCSI_ULP_COUNT] = { 0 }; | ||
3334 | 3583 | ||
3335 | idx = 0; | 3584 | idx = 0; |
3336 | mem_descr = phba->init_mem; | 3585 | mem_descr = phba->init_mem; |
@@ -3374,14 +3623,37 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
3374 | num_wrb_rings--; | 3623 | num_wrb_rings--; |
3375 | } | 3624 | } |
3376 | } | 3625 | } |
3626 | |||
3627 | /* Get the ULP Count */ | ||
3628 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
3629 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
3630 | ulp_count++; | ||
3631 | ulp_base_num = ulp_num; | ||
3632 | cid_count_ulp[ulp_num] = | ||
3633 | BEISCSI_GET_CID_COUNT(phba, ulp_num); | ||
3634 | } | ||
3635 | |||
3377 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | 3636 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { |
3378 | wrb_mem_index = 0; | 3637 | wrb_mem_index = 0; |
3379 | offset = 0; | 3638 | offset = 0; |
3380 | size = 0; | 3639 | size = 0; |
3381 | 3640 | ||
3641 | if (ulp_count > 1) { | ||
3642 | ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT; | ||
3643 | |||
3644 | if (!cid_count_ulp[ulp_base_num]) | ||
3645 | ulp_base_num = (ulp_base_num + 1) % | ||
3646 | BEISCSI_ULP_COUNT; | ||
3647 | |||
3648 | cid_count_ulp[ulp_base_num]--; | ||
3649 | } | ||
3650 | |||
3651 | |||
3382 | hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl); | 3652 | hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl); |
3383 | status = be_cmd_wrbq_create(&phba->ctrl, &sgl, | 3653 | status = be_cmd_wrbq_create(&phba->ctrl, &sgl, |
3384 | &phwi_context->be_wrbq[i]); | 3654 | &phwi_context->be_wrbq[i], |
3655 | &phwi_ctrlr->wrb_context[i], | ||
3656 | ulp_base_num); | ||
3385 | if (status != 0) { | 3657 | if (status != 0) { |
3386 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3658 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3387 | "BM_%d : wrbq create failed."); | 3659 | "BM_%d : wrbq create failed."); |
@@ -3389,7 +3661,6 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
3389 | return status; | 3661 | return status; |
3390 | } | 3662 | } |
3391 | pwrb_context = &phwi_ctrlr->wrb_context[i]; | 3663 | pwrb_context = &phwi_ctrlr->wrb_context[i]; |
3392 | pwrb_context->cid = phwi_context->be_wrbq[i].id; | ||
3393 | BE_SET_CID_TO_CRI(i, pwrb_context->cid); | 3664 | BE_SET_CID_TO_CRI(i, pwrb_context->cid); |
3394 | } | 3665 | } |
3395 | kfree(pwrb_arr); | 3666 | kfree(pwrb_arr); |
@@ -3433,10 +3704,13 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
3433 | struct hwi_controller *phwi_ctrlr; | 3704 | struct hwi_controller *phwi_ctrlr; |
3434 | struct hwi_context_memory *phwi_context; | 3705 | struct hwi_context_memory *phwi_context; |
3435 | struct hwi_async_pdu_context *pasync_ctx; | 3706 | struct hwi_async_pdu_context *pasync_ctx; |
3436 | int i, eq_num; | 3707 | int i, eq_num, ulp_num; |
3437 | 3708 | ||
3438 | phwi_ctrlr = phba->phwi_ctrlr; | 3709 | phwi_ctrlr = phba->phwi_ctrlr; |
3439 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3710 | phwi_context = phwi_ctrlr->phwi_ctxt; |
3711 | |||
3712 | be_cmd_iscsi_remove_template_hdr(ctrl); | ||
3713 | |||
3440 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | 3714 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { |
3441 | q = &phwi_context->be_wrbq[i]; | 3715 | q = &phwi_context->be_wrbq[i]; |
3442 | if (q->created) | 3716 | if (q->created) |
@@ -3445,13 +3719,20 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
3445 | kfree(phwi_context->be_wrbq); | 3719 | kfree(phwi_context->be_wrbq); |
3446 | free_wrb_handles(phba); | 3720 | free_wrb_handles(phba); |
3447 | 3721 | ||
3448 | q = &phwi_context->be_def_hdrq; | 3722 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
3449 | if (q->created) | 3723 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
3450 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
3451 | 3724 | ||
3452 | q = &phwi_context->be_def_dataq; | 3725 | q = &phwi_context->be_def_hdrq[ulp_num]; |
3453 | if (q->created) | 3726 | if (q->created) |
3454 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | 3727 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); |
3728 | |||
3729 | q = &phwi_context->be_def_dataq[ulp_num]; | ||
3730 | if (q->created) | ||
3731 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
3732 | |||
3733 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | ||
3734 | } | ||
3735 | } | ||
3455 | 3736 | ||
3456 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | 3737 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); |
3457 | 3738 | ||
@@ -3470,9 +3751,6 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
3470 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | 3751 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); |
3471 | } | 3752 | } |
3472 | be_mcc_queues_destroy(phba); | 3753 | be_mcc_queues_destroy(phba); |
3473 | |||
3474 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; | ||
3475 | kfree(pasync_ctx->async_entry); | ||
3476 | be_cmd_fw_uninit(ctrl); | 3754 | be_cmd_fw_uninit(ctrl); |
3477 | } | 3755 | } |
3478 | 3756 | ||
@@ -3538,8 +3816,19 @@ static void find_num_cpus(struct beiscsi_hba *phba) | |||
3538 | BEISCSI_MAX_NUM_CPUS : num_cpus; | 3816 | BEISCSI_MAX_NUM_CPUS : num_cpus; |
3539 | break; | 3817 | break; |
3540 | case BE_GEN4: | 3818 | case BE_GEN4: |
3541 | phba->num_cpus = (num_cpus > OC_SKH_MAX_NUM_CPUS) ? | 3819 | /* |
3542 | OC_SKH_MAX_NUM_CPUS : num_cpus; | 3820 | * If eqid_count == 1 fall back to |
3821 | * INTX mechanism | ||
3822 | **/ | ||
3823 | if (phba->fw_config.eqid_count == 1) { | ||
3824 | enable_msix = 0; | ||
3825 | phba->num_cpus = 1; | ||
3826 | return; | ||
3827 | } | ||
3828 | |||
3829 | phba->num_cpus = | ||
3830 | (num_cpus > (phba->fw_config.eqid_count - 1)) ? | ||
3831 | (phba->fw_config.eqid_count - 1) : num_cpus; | ||
3543 | break; | 3832 | break; |
3544 | default: | 3833 | default: |
3545 | phba->num_cpus = 1; | 3834 | phba->num_cpus = 1; |
@@ -3552,10 +3841,8 @@ static int hwi_init_port(struct beiscsi_hba *phba) | |||
3552 | struct hwi_context_memory *phwi_context; | 3841 | struct hwi_context_memory *phwi_context; |
3553 | unsigned int def_pdu_ring_sz; | 3842 | unsigned int def_pdu_ring_sz; |
3554 | struct be_ctrl_info *ctrl = &phba->ctrl; | 3843 | struct be_ctrl_info *ctrl = &phba->ctrl; |
3555 | int status; | 3844 | int status, ulp_num; |
3556 | 3845 | ||
3557 | def_pdu_ring_sz = | ||
3558 | phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr); | ||
3559 | phwi_ctrlr = phba->phwi_ctrlr; | 3846 | phwi_ctrlr = phba->phwi_ctrlr; |
3560 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3847 | phwi_context = phwi_ctrlr->phwi_ctxt; |
3561 | phwi_context->max_eqd = 0; | 3848 | phwi_context->max_eqd = 0; |
@@ -3588,27 +3875,48 @@ static int hwi_init_port(struct beiscsi_hba *phba) | |||
3588 | goto error; | 3875 | goto error; |
3589 | } | 3876 | } |
3590 | 3877 | ||
3591 | status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr, | 3878 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
3592 | def_pdu_ring_sz); | 3879 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
3593 | if (status != 0) { | 3880 | |
3594 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3881 | def_pdu_ring_sz = |
3595 | "BM_%d : Default Header not created\n"); | 3882 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
3596 | goto error; | 3883 | sizeof(struct phys_addr); |
3884 | |||
3885 | status = beiscsi_create_def_hdr(phba, phwi_context, | ||
3886 | phwi_ctrlr, | ||
3887 | def_pdu_ring_sz, | ||
3888 | ulp_num); | ||
3889 | if (status != 0) { | ||
3890 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
3891 | "BM_%d : Default Header not created for ULP : %d\n", | ||
3892 | ulp_num); | ||
3893 | goto error; | ||
3894 | } | ||
3895 | |||
3896 | status = beiscsi_create_def_data(phba, phwi_context, | ||
3897 | phwi_ctrlr, | ||
3898 | def_pdu_ring_sz, | ||
3899 | ulp_num); | ||
3900 | if (status != 0) { | ||
3901 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
3902 | "BM_%d : Default Data not created for ULP : %d\n", | ||
3903 | ulp_num); | ||
3904 | goto error; | ||
3905 | } | ||
3906 | } | ||
3597 | } | 3907 | } |
3598 | 3908 | ||
3599 | status = beiscsi_create_def_data(phba, phwi_context, | 3909 | status = beiscsi_post_pages(phba); |
3600 | phwi_ctrlr, def_pdu_ring_sz); | ||
3601 | if (status != 0) { | 3910 | if (status != 0) { |
3602 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3911 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3603 | "BM_%d : Default Data not created\n"); | 3912 | "BM_%d : Post SGL Pages Failed\n"); |
3604 | goto error; | 3913 | goto error; |
3605 | } | 3914 | } |
3606 | 3915 | ||
3607 | status = beiscsi_post_pages(phba); | 3916 | status = beiscsi_post_template_hdr(phba); |
3608 | if (status != 0) { | 3917 | if (status != 0) { |
3609 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3918 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3610 | "BM_%d : Post SGL Pages Failed\n"); | 3919 | "BM_%d : Template HDR Posting for CXN Failed\n"); |
3611 | goto error; | ||
3612 | } | 3920 | } |
3613 | 3921 | ||
3614 | status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr); | 3922 | status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr); |
@@ -3618,6 +3926,26 @@ static int hwi_init_port(struct beiscsi_hba *phba) | |||
3618 | goto error; | 3926 | goto error; |
3619 | } | 3927 | } |
3620 | 3928 | ||
3929 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
3930 | uint16_t async_arr_idx = 0; | ||
3931 | |||
3932 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
3933 | uint16_t cri = 0; | ||
3934 | struct hwi_async_pdu_context *pasync_ctx; | ||
3935 | |||
3936 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX( | ||
3937 | phwi_ctrlr, ulp_num); | ||
3938 | for (cri = 0; cri < | ||
3939 | phba->params.cxns_per_ctrl; cri++) { | ||
3940 | if (ulp_num == BEISCSI_GET_ULP_FROM_CRI | ||
3941 | (phwi_ctrlr, cri)) | ||
3942 | pasync_ctx->cid_to_async_cri_map[ | ||
3943 | phwi_ctrlr->wrb_context[cri].cid] = | ||
3944 | async_arr_idx++; | ||
3945 | } | ||
3946 | } | ||
3947 | } | ||
3948 | |||
3621 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 3949 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
3622 | "BM_%d : hwi_init_port success\n"); | 3950 | "BM_%d : hwi_init_port success\n"); |
3623 | return 0; | 3951 | return 0; |
@@ -3682,6 +4010,7 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba) | |||
3682 | (unsigned long)mem_descr->mem_array[j - 1]. | 4010 | (unsigned long)mem_descr->mem_array[j - 1]. |
3683 | bus_address.u.a64.address); | 4011 | bus_address.u.a64.address); |
3684 | } | 4012 | } |
4013 | |||
3685 | kfree(mem_descr->mem_array); | 4014 | kfree(mem_descr->mem_array); |
3686 | mem_descr++; | 4015 | mem_descr++; |
3687 | } | 4016 | } |
@@ -3721,6 +4050,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
3721 | struct sgl_handle *psgl_handle; | 4050 | struct sgl_handle *psgl_handle; |
3722 | struct iscsi_sge *pfrag; | 4051 | struct iscsi_sge *pfrag; |
3723 | unsigned int arr_index, i, idx; | 4052 | unsigned int arr_index, i, idx; |
4053 | unsigned int ulp_icd_start, ulp_num = 0; | ||
3724 | 4054 | ||
3725 | phba->io_sgl_hndl_avbl = 0; | 4055 | phba->io_sgl_hndl_avbl = 0; |
3726 | phba->eh_sgl_hndl_avbl = 0; | 4056 | phba->eh_sgl_hndl_avbl = 0; |
@@ -3787,6 +4117,12 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
3787 | "\n BM_%d : mem_descr_sg->num_elements=%d\n", | 4117 | "\n BM_%d : mem_descr_sg->num_elements=%d\n", |
3788 | mem_descr_sg->num_elements); | 4118 | mem_descr_sg->num_elements); |
3789 | 4119 | ||
4120 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
4121 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) | ||
4122 | break; | ||
4123 | |||
4124 | ulp_icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; | ||
4125 | |||
3790 | arr_index = 0; | 4126 | arr_index = 0; |
3791 | idx = 0; | 4127 | idx = 0; |
3792 | while (idx < mem_descr_sg->num_elements) { | 4128 | while (idx < mem_descr_sg->num_elements) { |
@@ -3805,8 +4141,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
3805 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0); | 4141 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0); |
3806 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); | 4142 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); |
3807 | pfrag += phba->params.num_sge_per_io; | 4143 | pfrag += phba->params.num_sge_per_io; |
3808 | psgl_handle->sgl_index = | 4144 | psgl_handle->sgl_index = ulp_icd_start + arr_index++; |
3809 | phba->fw_config.iscsi_icd_start + arr_index++; | ||
3810 | } | 4145 | } |
3811 | idx++; | 4146 | idx++; |
3812 | } | 4147 | } |
@@ -3819,15 +4154,46 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
3819 | 4154 | ||
3820 | static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | 4155 | static int hba_setup_cid_tbls(struct beiscsi_hba *phba) |
3821 | { | 4156 | { |
3822 | int i; | 4157 | int ret; |
4158 | uint16_t i, ulp_num; | ||
4159 | struct ulp_cid_info *ptr_cid_info = NULL; | ||
3823 | 4160 | ||
3824 | phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, | 4161 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
3825 | GFP_KERNEL); | 4162 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { |
3826 | if (!phba->cid_array) { | 4163 | ptr_cid_info = kzalloc(sizeof(struct ulp_cid_info), |
3827 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 4164 | GFP_KERNEL); |
3828 | "BM_%d : Failed to allocate memory in " | 4165 | |
3829 | "hba_setup_cid_tbls\n"); | 4166 | if (!ptr_cid_info) { |
3830 | return -ENOMEM; | 4167 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
4168 | "BM_%d : Failed to allocate memory" | ||
4169 | "for ULP_CID_INFO for ULP : %d\n", | ||
4170 | ulp_num); | ||
4171 | ret = -ENOMEM; | ||
4172 | goto free_memory; | ||
4173 | |||
4174 | } | ||
4175 | |||
4176 | /* Allocate memory for CID array */ | ||
4177 | ptr_cid_info->cid_array = kzalloc(sizeof(void *) * | ||
4178 | BEISCSI_GET_CID_COUNT(phba, | ||
4179 | ulp_num), GFP_KERNEL); | ||
4180 | if (!ptr_cid_info->cid_array) { | ||
4181 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
4182 | "BM_%d : Failed to allocate memory" | ||
4183 | "for CID_ARRAY for ULP : %d\n", | ||
4184 | ulp_num); | ||
4185 | kfree(ptr_cid_info); | ||
4186 | ptr_cid_info = NULL; | ||
4187 | ret = -ENOMEM; | ||
4188 | |||
4189 | goto free_memory; | ||
4190 | } | ||
4191 | ptr_cid_info->avlbl_cids = BEISCSI_GET_CID_COUNT( | ||
4192 | phba, ulp_num); | ||
4193 | |||
4194 | /* Save the cid_info_array ptr */ | ||
4195 | phba->cid_array_info[ulp_num] = ptr_cid_info; | ||
4196 | } | ||
3831 | } | 4197 | } |
3832 | phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * | 4198 | phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * |
3833 | phba->params.cxns_per_ctrl, GFP_KERNEL); | 4199 | phba->params.cxns_per_ctrl, GFP_KERNEL); |
@@ -3835,9 +4201,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
3835 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 4201 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
3836 | "BM_%d : Failed to allocate memory in " | 4202 | "BM_%d : Failed to allocate memory in " |
3837 | "hba_setup_cid_tbls\n"); | 4203 | "hba_setup_cid_tbls\n"); |
3838 | kfree(phba->cid_array); | 4204 | ret = -ENOMEM; |
3839 | phba->cid_array = NULL; | 4205 | |
3840 | return -ENOMEM; | 4206 | goto free_memory; |
3841 | } | 4207 | } |
3842 | 4208 | ||
3843 | phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * | 4209 | phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * |
@@ -3847,18 +4213,44 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
3847 | "BM_%d : Failed to allocate memory in" | 4213 | "BM_%d : Failed to allocate memory in" |
3848 | "hba_setup_cid_tbls\n"); | 4214 | "hba_setup_cid_tbls\n"); |
3849 | 4215 | ||
3850 | kfree(phba->cid_array); | ||
3851 | kfree(phba->ep_array); | 4216 | kfree(phba->ep_array); |
3852 | phba->cid_array = NULL; | ||
3853 | phba->ep_array = NULL; | 4217 | phba->ep_array = NULL; |
3854 | return -ENOMEM; | 4218 | ret = -ENOMEM; |
4219 | } | ||
4220 | |||
4221 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
4222 | ulp_num = phba->phwi_ctrlr->wrb_context[i].ulp_num; | ||
4223 | |||
4224 | ptr_cid_info = phba->cid_array_info[ulp_num]; | ||
4225 | ptr_cid_info->cid_array[ptr_cid_info->cid_alloc++] = | ||
4226 | phba->phwi_ctrlr->wrb_context[i].cid; | ||
4227 | |||
3855 | } | 4228 | } |
3856 | 4229 | ||
3857 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) | 4230 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
3858 | phba->cid_array[i] = phba->phwi_ctrlr->wrb_context[i].cid; | 4231 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { |
4232 | ptr_cid_info = phba->cid_array_info[ulp_num]; | ||
3859 | 4233 | ||
3860 | phba->avlbl_cids = phba->params.cxns_per_ctrl; | 4234 | ptr_cid_info->cid_alloc = 0; |
4235 | ptr_cid_info->cid_free = 0; | ||
4236 | } | ||
4237 | } | ||
3861 | return 0; | 4238 | return 0; |
4239 | |||
4240 | free_memory: | ||
4241 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
4242 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { | ||
4243 | ptr_cid_info = phba->cid_array_info[ulp_num]; | ||
4244 | |||
4245 | if (ptr_cid_info) { | ||
4246 | kfree(ptr_cid_info->cid_array); | ||
4247 | kfree(ptr_cid_info); | ||
4248 | phba->cid_array_info[ulp_num] = NULL; | ||
4249 | } | ||
4250 | } | ||
4251 | } | ||
4252 | |||
4253 | return ret; | ||
3862 | } | 4254 | } |
3863 | 4255 | ||
3864 | static void hwi_enable_intr(struct beiscsi_hba *phba) | 4256 | static void hwi_enable_intr(struct beiscsi_hba *phba) |
@@ -4113,20 +4505,39 @@ static void hwi_purge_eq(struct beiscsi_hba *phba) | |||
4113 | 4505 | ||
4114 | static void beiscsi_clean_port(struct beiscsi_hba *phba) | 4506 | static void beiscsi_clean_port(struct beiscsi_hba *phba) |
4115 | { | 4507 | { |
4116 | int mgmt_status; | 4508 | int mgmt_status, ulp_num; |
4117 | 4509 | struct ulp_cid_info *ptr_cid_info = NULL; | |
4118 | mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); | 4510 | |
4119 | if (mgmt_status) | 4511 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
4120 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | 4512 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { |
4121 | "BM_%d : mgmt_epfw_cleanup FAILED\n"); | 4513 | mgmt_status = mgmt_epfw_cleanup(phba, ulp_num); |
4514 | if (mgmt_status) | ||
4515 | beiscsi_log(phba, KERN_WARNING, | ||
4516 | BEISCSI_LOG_INIT, | ||
4517 | "BM_%d : mgmt_epfw_cleanup FAILED" | ||
4518 | " for ULP_%d\n", ulp_num); | ||
4519 | } | ||
4520 | } | ||
4122 | 4521 | ||
4123 | hwi_purge_eq(phba); | 4522 | hwi_purge_eq(phba); |
4124 | hwi_cleanup(phba); | 4523 | hwi_cleanup(phba); |
4125 | kfree(phba->io_sgl_hndl_base); | 4524 | kfree(phba->io_sgl_hndl_base); |
4126 | kfree(phba->eh_sgl_hndl_base); | 4525 | kfree(phba->eh_sgl_hndl_base); |
4127 | kfree(phba->cid_array); | ||
4128 | kfree(phba->ep_array); | 4526 | kfree(phba->ep_array); |
4129 | kfree(phba->conn_table); | 4527 | kfree(phba->conn_table); |
4528 | |||
4529 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
4530 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { | ||
4531 | ptr_cid_info = phba->cid_array_info[ulp_num]; | ||
4532 | |||
4533 | if (ptr_cid_info) { | ||
4534 | kfree(ptr_cid_info->cid_array); | ||
4535 | kfree(ptr_cid_info); | ||
4536 | phba->cid_array_info[ulp_num] = NULL; | ||
4537 | } | ||
4538 | } | ||
4539 | } | ||
4540 | |||
4130 | } | 4541 | } |
4131 | 4542 | ||
4132 | /** | 4543 | /** |
@@ -4255,8 +4666,8 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | |||
4255 | doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) | 4666 | doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) |
4256 | << DB_DEF_PDU_WRB_INDEX_SHIFT; | 4667 | << DB_DEF_PDU_WRB_INDEX_SHIFT; |
4257 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 4668 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
4258 | 4669 | iowrite32(doorbell, phba->db_va + | |
4259 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | 4670 | beiscsi_conn->doorbell_offset); |
4260 | } | 4671 | } |
4261 | 4672 | ||
4262 | static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, | 4673 | static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, |
@@ -4481,7 +4892,8 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, | |||
4481 | DB_DEF_PDU_WRB_INDEX_MASK) << | 4892 | DB_DEF_PDU_WRB_INDEX_MASK) << |
4482 | DB_DEF_PDU_WRB_INDEX_SHIFT; | 4893 | DB_DEF_PDU_WRB_INDEX_SHIFT; |
4483 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 4894 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
4484 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | 4895 | iowrite32(doorbell, phba->db_va + |
4896 | beiscsi_conn->doorbell_offset); | ||
4485 | return 0; | 4897 | return 0; |
4486 | } | 4898 | } |
4487 | 4899 | ||
@@ -4536,7 +4948,8 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | |||
4536 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; | 4948 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; |
4537 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 4949 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
4538 | 4950 | ||
4539 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | 4951 | iowrite32(doorbell, phba->db_va + |
4952 | beiscsi_conn->doorbell_offset); | ||
4540 | return 0; | 4953 | return 0; |
4541 | } | 4954 | } |
4542 | 4955 | ||
@@ -4638,7 +5051,8 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
4638 | doorbell |= (io_task->pwrb_handle->wrb_index & | 5051 | doorbell |= (io_task->pwrb_handle->wrb_index & |
4639 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; | 5052 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; |
4640 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | 5053 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; |
4641 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | 5054 | iowrite32(doorbell, phba->db_va + |
5055 | beiscsi_conn->doorbell_offset); | ||
4642 | return 0; | 5056 | return 0; |
4643 | } | 5057 | } |
4644 | 5058 | ||
@@ -4663,8 +5077,12 @@ static int beiscsi_task_xmit(struct iscsi_task *task) | |||
4663 | struct beiscsi_hba *phba = NULL; | 5077 | struct beiscsi_hba *phba = NULL; |
4664 | 5078 | ||
4665 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; | 5079 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; |
4666 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO, | 5080 | beiscsi_log(phba, KERN_ERR, |
4667 | "BM_%d : scsi_dma_map Failed\n"); | 5081 | BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, |
5082 | "BM_%d : scsi_dma_map Failed " | ||
5083 | "Driver_ITT : 0x%x ITT : 0x%x Xferlen : 0x%x\n", | ||
5084 | be32_to_cpu(io_task->cmd_bhs->iscsi_hdr.itt), | ||
5085 | io_task->libiscsi_itt, scsi_bufflen(sc)); | ||
4668 | 5086 | ||
4669 | return num_sg; | 5087 | return num_sg; |
4670 | } | 5088 | } |
@@ -4769,10 +5187,12 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) | |||
4769 | /* | 5187 | /* |
4770 | * beiscsi_quiesce()- Cleanup Driver resources | 5188 | * beiscsi_quiesce()- Cleanup Driver resources |
4771 | * @phba: Instance Priv structure | 5189 | * @phba: Instance Priv structure |
5190 | * @unload_state:i Clean or EEH unload state | ||
4772 | * | 5191 | * |
4773 | * Free the OS and HW resources held by the driver | 5192 | * Free the OS and HW resources held by the driver |
4774 | **/ | 5193 | **/ |
4775 | static void beiscsi_quiesce(struct beiscsi_hba *phba) | 5194 | static void beiscsi_quiesce(struct beiscsi_hba *phba, |
5195 | uint32_t unload_state) | ||
4776 | { | 5196 | { |
4777 | struct hwi_controller *phwi_ctrlr; | 5197 | struct hwi_controller *phwi_ctrlr; |
4778 | struct hwi_context_memory *phwi_context; | 5198 | struct hwi_context_memory *phwi_context; |
@@ -4785,28 +5205,37 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba) | |||
4785 | if (phba->msix_enabled) { | 5205 | if (phba->msix_enabled) { |
4786 | for (i = 0; i <= phba->num_cpus; i++) { | 5206 | for (i = 0; i <= phba->num_cpus; i++) { |
4787 | msix_vec = phba->msix_entries[i].vector; | 5207 | msix_vec = phba->msix_entries[i].vector; |
5208 | synchronize_irq(msix_vec); | ||
4788 | free_irq(msix_vec, &phwi_context->be_eq[i]); | 5209 | free_irq(msix_vec, &phwi_context->be_eq[i]); |
4789 | kfree(phba->msi_name[i]); | 5210 | kfree(phba->msi_name[i]); |
4790 | } | 5211 | } |
4791 | } else | 5212 | } else |
4792 | if (phba->pcidev->irq) | 5213 | if (phba->pcidev->irq) { |
5214 | synchronize_irq(phba->pcidev->irq); | ||
4793 | free_irq(phba->pcidev->irq, phba); | 5215 | free_irq(phba->pcidev->irq, phba); |
5216 | } | ||
4794 | pci_disable_msix(phba->pcidev); | 5217 | pci_disable_msix(phba->pcidev); |
4795 | destroy_workqueue(phba->wq); | 5218 | |
4796 | if (blk_iopoll_enabled) | 5219 | if (blk_iopoll_enabled) |
4797 | for (i = 0; i < phba->num_cpus; i++) { | 5220 | for (i = 0; i < phba->num_cpus; i++) { |
4798 | pbe_eq = &phwi_context->be_eq[i]; | 5221 | pbe_eq = &phwi_context->be_eq[i]; |
4799 | blk_iopoll_disable(&pbe_eq->iopoll); | 5222 | blk_iopoll_disable(&pbe_eq->iopoll); |
4800 | } | 5223 | } |
4801 | 5224 | ||
4802 | beiscsi_clean_port(phba); | 5225 | if (unload_state == BEISCSI_CLEAN_UNLOAD) { |
4803 | beiscsi_free_mem(phba); | 5226 | destroy_workqueue(phba->wq); |
5227 | beiscsi_clean_port(phba); | ||
5228 | beiscsi_free_mem(phba); | ||
4804 | 5229 | ||
4805 | beiscsi_unmap_pci_function(phba); | 5230 | beiscsi_unmap_pci_function(phba); |
4806 | pci_free_consistent(phba->pcidev, | 5231 | pci_free_consistent(phba->pcidev, |
4807 | phba->ctrl.mbox_mem_alloced.size, | 5232 | phba->ctrl.mbox_mem_alloced.size, |
4808 | phba->ctrl.mbox_mem_alloced.va, | 5233 | phba->ctrl.mbox_mem_alloced.va, |
4809 | phba->ctrl.mbox_mem_alloced.dma); | 5234 | phba->ctrl.mbox_mem_alloced.dma); |
5235 | } else { | ||
5236 | hwi_purge_eq(phba); | ||
5237 | hwi_cleanup(phba); | ||
5238 | } | ||
4810 | 5239 | ||
4811 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); | 5240 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); |
4812 | } | 5241 | } |
@@ -4823,11 +5252,13 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
4823 | } | 5252 | } |
4824 | 5253 | ||
4825 | beiscsi_destroy_def_ifaces(phba); | 5254 | beiscsi_destroy_def_ifaces(phba); |
4826 | beiscsi_quiesce(phba); | 5255 | beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); |
4827 | iscsi_boot_destroy_kset(phba->boot_kset); | 5256 | iscsi_boot_destroy_kset(phba->boot_kset); |
4828 | iscsi_host_remove(phba->shost); | 5257 | iscsi_host_remove(phba->shost); |
4829 | pci_dev_put(phba->pcidev); | 5258 | pci_dev_put(phba->pcidev); |
4830 | iscsi_host_free(phba->shost); | 5259 | iscsi_host_free(phba->shost); |
5260 | pci_disable_pcie_error_reporting(pcidev); | ||
5261 | pci_set_drvdata(pcidev, NULL); | ||
4831 | pci_disable_device(pcidev); | 5262 | pci_disable_device(pcidev); |
4832 | } | 5263 | } |
4833 | 5264 | ||
@@ -4842,7 +5273,7 @@ static void beiscsi_shutdown(struct pci_dev *pcidev) | |||
4842 | return; | 5273 | return; |
4843 | } | 5274 | } |
4844 | 5275 | ||
4845 | beiscsi_quiesce(phba); | 5276 | beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); |
4846 | pci_disable_device(pcidev); | 5277 | pci_disable_device(pcidev); |
4847 | } | 5278 | } |
4848 | 5279 | ||
@@ -4880,6 +5311,167 @@ beiscsi_hw_health_check(struct work_struct *work) | |||
4880 | msecs_to_jiffies(1000)); | 5311 | msecs_to_jiffies(1000)); |
4881 | } | 5312 | } |
4882 | 5313 | ||
5314 | |||
5315 | static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, | ||
5316 | pci_channel_state_t state) | ||
5317 | { | ||
5318 | struct beiscsi_hba *phba = NULL; | ||
5319 | |||
5320 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5321 | phba->state |= BE_ADAPTER_PCI_ERR; | ||
5322 | |||
5323 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5324 | "BM_%d : EEH error detected\n"); | ||
5325 | |||
5326 | beiscsi_quiesce(phba, BEISCSI_EEH_UNLOAD); | ||
5327 | |||
5328 | if (state == pci_channel_io_perm_failure) { | ||
5329 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5330 | "BM_%d : EEH : State PERM Failure"); | ||
5331 | return PCI_ERS_RESULT_DISCONNECT; | ||
5332 | } | ||
5333 | |||
5334 | pci_disable_device(pdev); | ||
5335 | |||
5336 | /* The error could cause the FW to trigger a flash debug dump. | ||
5337 | * Resetting the card while flash dump is in progress | ||
5338 | * can cause it not to recover; wait for it to finish. | ||
5339 | * Wait only for first function as it is needed only once per | ||
5340 | * adapter. | ||
5341 | **/ | ||
5342 | if (pdev->devfn == 0) | ||
5343 | ssleep(30); | ||
5344 | |||
5345 | return PCI_ERS_RESULT_NEED_RESET; | ||
5346 | } | ||
5347 | |||
5348 | static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) | ||
5349 | { | ||
5350 | struct beiscsi_hba *phba = NULL; | ||
5351 | int status = 0; | ||
5352 | |||
5353 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5354 | |||
5355 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5356 | "BM_%d : EEH Reset\n"); | ||
5357 | |||
5358 | status = pci_enable_device(pdev); | ||
5359 | if (status) | ||
5360 | return PCI_ERS_RESULT_DISCONNECT; | ||
5361 | |||
5362 | pci_set_master(pdev); | ||
5363 | pci_set_power_state(pdev, PCI_D0); | ||
5364 | pci_restore_state(pdev); | ||
5365 | |||
5366 | /* Wait for the CHIP Reset to complete */ | ||
5367 | status = be_chk_reset_complete(phba); | ||
5368 | if (!status) { | ||
5369 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5370 | "BM_%d : EEH Reset Completed\n"); | ||
5371 | } else { | ||
5372 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5373 | "BM_%d : EEH Reset Completion Failure\n"); | ||
5374 | return PCI_ERS_RESULT_DISCONNECT; | ||
5375 | } | ||
5376 | |||
5377 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
5378 | return PCI_ERS_RESULT_RECOVERED; | ||
5379 | } | ||
5380 | |||
5381 | static void beiscsi_eeh_resume(struct pci_dev *pdev) | ||
5382 | { | ||
5383 | int ret = 0, i; | ||
5384 | struct be_eq_obj *pbe_eq; | ||
5385 | struct beiscsi_hba *phba = NULL; | ||
5386 | struct hwi_controller *phwi_ctrlr; | ||
5387 | struct hwi_context_memory *phwi_context; | ||
5388 | |||
5389 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | ||
5390 | pci_save_state(pdev); | ||
5391 | |||
5392 | if (enable_msix) | ||
5393 | find_num_cpus(phba); | ||
5394 | else | ||
5395 | phba->num_cpus = 1; | ||
5396 | |||
5397 | if (enable_msix) { | ||
5398 | beiscsi_msix_enable(phba); | ||
5399 | if (!phba->msix_enabled) | ||
5400 | phba->num_cpus = 1; | ||
5401 | } | ||
5402 | |||
5403 | ret = beiscsi_cmd_reset_function(phba); | ||
5404 | if (ret) { | ||
5405 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5406 | "BM_%d : Reset Failed\n"); | ||
5407 | goto ret_err; | ||
5408 | } | ||
5409 | |||
5410 | ret = be_chk_reset_complete(phba); | ||
5411 | if (ret) { | ||
5412 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5413 | "BM_%d : Failed to get out of reset.\n"); | ||
5414 | goto ret_err; | ||
5415 | } | ||
5416 | |||
5417 | beiscsi_get_params(phba); | ||
5418 | phba->shost->max_id = phba->params.cxns_per_ctrl; | ||
5419 | phba->shost->can_queue = phba->params.ios_per_ctrl; | ||
5420 | ret = hwi_init_controller(phba); | ||
5421 | |||
5422 | for (i = 0; i < MAX_MCC_CMD; i++) { | ||
5423 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
5424 | phba->ctrl.mcc_tag[i] = i + 1; | ||
5425 | phba->ctrl.mcc_numtag[i + 1] = 0; | ||
5426 | phba->ctrl.mcc_tag_available++; | ||
5427 | } | ||
5428 | |||
5429 | phwi_ctrlr = phba->phwi_ctrlr; | ||
5430 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
5431 | |||
5432 | if (blk_iopoll_enabled) { | ||
5433 | for (i = 0; i < phba->num_cpus; i++) { | ||
5434 | pbe_eq = &phwi_context->be_eq[i]; | ||
5435 | blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, | ||
5436 | be_iopoll); | ||
5437 | blk_iopoll_enable(&pbe_eq->iopoll); | ||
5438 | } | ||
5439 | |||
5440 | i = (phba->msix_enabled) ? i : 0; | ||
5441 | /* Work item for MCC handling */ | ||
5442 | pbe_eq = &phwi_context->be_eq[i]; | ||
5443 | INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); | ||
5444 | } else { | ||
5445 | if (phba->msix_enabled) { | ||
5446 | for (i = 0; i <= phba->num_cpus; i++) { | ||
5447 | pbe_eq = &phwi_context->be_eq[i]; | ||
5448 | INIT_WORK(&pbe_eq->work_cqs, | ||
5449 | beiscsi_process_all_cqs); | ||
5450 | } | ||
5451 | } else { | ||
5452 | pbe_eq = &phwi_context->be_eq[0]; | ||
5453 | INIT_WORK(&pbe_eq->work_cqs, | ||
5454 | beiscsi_process_all_cqs); | ||
5455 | } | ||
5456 | } | ||
5457 | |||
5458 | ret = beiscsi_init_irqs(phba); | ||
5459 | if (ret < 0) { | ||
5460 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5461 | "BM_%d : beiscsi_eeh_resume - " | ||
5462 | "Failed to beiscsi_init_irqs\n"); | ||
5463 | goto ret_err; | ||
5464 | } | ||
5465 | |||
5466 | hwi_enable_intr(phba); | ||
5467 | phba->state &= ~BE_ADAPTER_PCI_ERR; | ||
5468 | |||
5469 | return; | ||
5470 | ret_err: | ||
5471 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
5472 | "BM_%d : AER EEH Resume Failed\n"); | ||
5473 | } | ||
5474 | |||
4883 | static int beiscsi_dev_probe(struct pci_dev *pcidev, | 5475 | static int beiscsi_dev_probe(struct pci_dev *pcidev, |
4884 | const struct pci_device_id *id) | 5476 | const struct pci_device_id *id) |
4885 | { | 5477 | { |
@@ -4887,7 +5479,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4887 | struct hwi_controller *phwi_ctrlr; | 5479 | struct hwi_controller *phwi_ctrlr; |
4888 | struct hwi_context_memory *phwi_context; | 5480 | struct hwi_context_memory *phwi_context; |
4889 | struct be_eq_obj *pbe_eq; | 5481 | struct be_eq_obj *pbe_eq; |
4890 | int ret, i; | 5482 | int ret = 0, i; |
4891 | 5483 | ||
4892 | ret = beiscsi_enable_pci(pcidev); | 5484 | ret = beiscsi_enable_pci(pcidev); |
4893 | if (ret < 0) { | 5485 | if (ret < 0) { |
@@ -4903,10 +5495,20 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4903 | goto disable_pci; | 5495 | goto disable_pci; |
4904 | } | 5496 | } |
4905 | 5497 | ||
5498 | /* Enable EEH reporting */ | ||
5499 | ret = pci_enable_pcie_error_reporting(pcidev); | ||
5500 | if (ret) | ||
5501 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
5502 | "BM_%d : PCIe Error Reporting " | ||
5503 | "Enabling Failed\n"); | ||
5504 | |||
5505 | pci_save_state(pcidev); | ||
5506 | |||
4906 | /* Initialize Driver configuration Paramters */ | 5507 | /* Initialize Driver configuration Paramters */ |
4907 | beiscsi_hba_attrs_init(phba); | 5508 | beiscsi_hba_attrs_init(phba); |
4908 | 5509 | ||
4909 | phba->fw_timeout = false; | 5510 | phba->fw_timeout = false; |
5511 | phba->mac_addr_set = false; | ||
4910 | 5512 | ||
4911 | 5513 | ||
4912 | switch (pcidev->device) { | 5514 | switch (pcidev->device) { |
@@ -4929,20 +5531,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4929 | phba->generation = 0; | 5531 | phba->generation = 0; |
4930 | } | 5532 | } |
4931 | 5533 | ||
4932 | if (enable_msix) | ||
4933 | find_num_cpus(phba); | ||
4934 | else | ||
4935 | phba->num_cpus = 1; | ||
4936 | |||
4937 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
4938 | "BM_%d : num_cpus = %d\n", | ||
4939 | phba->num_cpus); | ||
4940 | |||
4941 | if (enable_msix) { | ||
4942 | beiscsi_msix_enable(phba); | ||
4943 | if (!phba->msix_enabled) | ||
4944 | phba->num_cpus = 1; | ||
4945 | } | ||
4946 | ret = be_ctrl_init(phba, pcidev); | 5534 | ret = be_ctrl_init(phba, pcidev); |
4947 | if (ret) { | 5535 | if (ret) { |
4948 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5536 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
@@ -4954,27 +5542,43 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4954 | ret = beiscsi_cmd_reset_function(phba); | 5542 | ret = beiscsi_cmd_reset_function(phba); |
4955 | if (ret) { | 5543 | if (ret) { |
4956 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5544 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
4957 | "BM_%d : Reset Failed. Aborting Crashdump\n"); | 5545 | "BM_%d : Reset Failed\n"); |
4958 | goto hba_free; | 5546 | goto hba_free; |
4959 | } | 5547 | } |
4960 | ret = be_chk_reset_complete(phba); | 5548 | ret = be_chk_reset_complete(phba); |
4961 | if (ret) { | 5549 | if (ret) { |
4962 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5550 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
4963 | "BM_%d : Failed to get out of reset." | 5551 | "BM_%d : Failed to get out of reset.\n"); |
4964 | "Aborting Crashdump\n"); | ||
4965 | goto hba_free; | 5552 | goto hba_free; |
4966 | } | 5553 | } |
4967 | 5554 | ||
4968 | spin_lock_init(&phba->io_sgl_lock); | 5555 | spin_lock_init(&phba->io_sgl_lock); |
4969 | spin_lock_init(&phba->mgmt_sgl_lock); | 5556 | spin_lock_init(&phba->mgmt_sgl_lock); |
4970 | spin_lock_init(&phba->isr_lock); | 5557 | spin_lock_init(&phba->isr_lock); |
5558 | spin_lock_init(&phba->async_pdu_lock); | ||
4971 | ret = mgmt_get_fw_config(&phba->ctrl, phba); | 5559 | ret = mgmt_get_fw_config(&phba->ctrl, phba); |
4972 | if (ret != 0) { | 5560 | if (ret != 0) { |
4973 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5561 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
4974 | "BM_%d : Error getting fw config\n"); | 5562 | "BM_%d : Error getting fw config\n"); |
4975 | goto free_port; | 5563 | goto free_port; |
4976 | } | 5564 | } |
4977 | phba->shost->max_id = phba->fw_config.iscsi_cid_count; | 5565 | |
5566 | if (enable_msix) | ||
5567 | find_num_cpus(phba); | ||
5568 | else | ||
5569 | phba->num_cpus = 1; | ||
5570 | |||
5571 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
5572 | "BM_%d : num_cpus = %d\n", | ||
5573 | phba->num_cpus); | ||
5574 | |||
5575 | if (enable_msix) { | ||
5576 | beiscsi_msix_enable(phba); | ||
5577 | if (!phba->msix_enabled) | ||
5578 | phba->num_cpus = 1; | ||
5579 | } | ||
5580 | |||
5581 | phba->shost->max_id = phba->params.cxns_per_ctrl; | ||
4978 | beiscsi_get_params(phba); | 5582 | beiscsi_get_params(phba); |
4979 | phba->shost->can_queue = phba->params.ios_per_ctrl; | 5583 | phba->shost->can_queue = phba->params.ios_per_ctrl; |
4980 | ret = beiscsi_init_port(phba); | 5584 | ret = beiscsi_init_port(phba); |
@@ -4985,7 +5589,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4985 | goto free_port; | 5589 | goto free_port; |
4986 | } | 5590 | } |
4987 | 5591 | ||
4988 | for (i = 0; i < MAX_MCC_CMD ; i++) { | 5592 | for (i = 0; i < MAX_MCC_CMD; i++) { |
4989 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | 5593 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); |
4990 | phba->ctrl.mcc_tag[i] = i + 1; | 5594 | phba->ctrl.mcc_tag[i] = i + 1; |
4991 | phba->ctrl.mcc_numtag[i + 1] = 0; | 5595 | phba->ctrl.mcc_numtag[i + 1] = 0; |
@@ -5089,6 +5693,12 @@ disable_pci: | |||
5089 | return ret; | 5693 | return ret; |
5090 | } | 5694 | } |
5091 | 5695 | ||
5696 | static struct pci_error_handlers beiscsi_eeh_handlers = { | ||
5697 | .error_detected = beiscsi_eeh_err_detected, | ||
5698 | .slot_reset = beiscsi_eeh_reset, | ||
5699 | .resume = beiscsi_eeh_resume, | ||
5700 | }; | ||
5701 | |||
5092 | struct iscsi_transport beiscsi_iscsi_transport = { | 5702 | struct iscsi_transport beiscsi_iscsi_transport = { |
5093 | .owner = THIS_MODULE, | 5703 | .owner = THIS_MODULE, |
5094 | .name = DRV_NAME, | 5704 | .name = DRV_NAME, |
@@ -5127,7 +5737,8 @@ static struct pci_driver beiscsi_pci_driver = { | |||
5127 | .probe = beiscsi_dev_probe, | 5737 | .probe = beiscsi_dev_probe, |
5128 | .remove = beiscsi_remove, | 5738 | .remove = beiscsi_remove, |
5129 | .shutdown = beiscsi_shutdown, | 5739 | .shutdown = beiscsi_shutdown, |
5130 | .id_table = beiscsi_pci_id_table | 5740 | .id_table = beiscsi_pci_id_table, |
5741 | .err_handler = &beiscsi_eeh_handlers | ||
5131 | }; | 5742 | }; |
5132 | 5743 | ||
5133 | 5744 | ||
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 2c06ef3c02ac..31fa27b4a9b2 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/in.h> | 26 | #include <linux/in.h> |
27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/aer.h> | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
31 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
@@ -34,9 +35,8 @@ | |||
34 | #include <scsi/libiscsi.h> | 35 | #include <scsi/libiscsi.h> |
35 | #include <scsi/scsi_transport_iscsi.h> | 36 | #include <scsi/scsi_transport_iscsi.h> |
36 | 37 | ||
37 | #include "be.h" | ||
38 | #define DRV_NAME "be2iscsi" | 38 | #define DRV_NAME "be2iscsi" |
39 | #define BUILD_STR "10.0.467.0" | 39 | #define BUILD_STR "10.0.659.0" |
40 | #define BE_NAME "Emulex OneConnect" \ | 40 | #define BE_NAME "Emulex OneConnect" \ |
41 | "Open-iSCSI Driver version" BUILD_STR | 41 | "Open-iSCSI Driver version" BUILD_STR |
42 | #define DRV_DESC BE_NAME " " "Driver" | 42 | #define DRV_DESC BE_NAME " " "Driver" |
@@ -66,7 +66,6 @@ | |||
66 | 66 | ||
67 | #define MAX_CPUS 64 | 67 | #define MAX_CPUS 64 |
68 | #define BEISCSI_MAX_NUM_CPUS 7 | 68 | #define BEISCSI_MAX_NUM_CPUS 7 |
69 | #define OC_SKH_MAX_NUM_CPUS 31 | ||
70 | 69 | ||
71 | #define BEISCSI_VER_STRLEN 32 | 70 | #define BEISCSI_VER_STRLEN 32 |
72 | 71 | ||
@@ -74,6 +73,7 @@ | |||
74 | 73 | ||
75 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | 74 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ |
76 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ | 75 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ |
76 | #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ | ||
77 | 77 | ||
78 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | 78 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ |
79 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ | 79 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ |
@@ -97,14 +97,19 @@ | |||
97 | 97 | ||
98 | #define INVALID_SESS_HANDLE 0xFFFFFFFF | 98 | #define INVALID_SESS_HANDLE 0xFFFFFFFF |
99 | 99 | ||
100 | #define BE_ADAPTER_UP 0x00000000 | 100 | #define BE_ADAPTER_LINK_UP 0x001 |
101 | #define BE_ADAPTER_LINK_DOWN 0x00000001 | 101 | #define BE_ADAPTER_LINK_DOWN 0x002 |
102 | #define BE_ADAPTER_PCI_ERR 0x004 | ||
103 | |||
104 | #define BEISCSI_CLEAN_UNLOAD 0x01 | ||
105 | #define BEISCSI_EEH_UNLOAD 0x02 | ||
102 | /** | 106 | /** |
103 | * hardware needs the async PDU buffers to be posted in multiples of 8 | 107 | * hardware needs the async PDU buffers to be posted in multiples of 8 |
104 | * So have atleast 8 of them by default | 108 | * So have atleast 8 of them by default |
105 | */ | 109 | */ |
106 | 110 | ||
107 | #define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx) | 111 | #define HWI_GET_ASYNC_PDU_CTX(phwi, ulp_num) \ |
112 | (phwi->phwi_ctxt->pasync_ctx[ulp_num]) | ||
108 | 113 | ||
109 | /********* Memory BAR register ************/ | 114 | /********* Memory BAR register ************/ |
110 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc | 115 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc |
@@ -149,29 +154,41 @@ | |||
149 | #define DB_CQ_REARM_SHIFT (29) /* bit 29 */ | 154 | #define DB_CQ_REARM_SHIFT (29) /* bit 29 */ |
150 | 155 | ||
151 | #define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr) | 156 | #define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr) |
152 | #define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\ | 157 | #define HWI_GET_DEF_BUFQ_ID(pc, ulp_num) (((struct hwi_controller *)\ |
153 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id) | 158 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data[ulp_num].id) |
154 | #define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\ | 159 | #define HWI_GET_DEF_HDRQ_ID(pc, ulp_num) (((struct hwi_controller *)\ |
155 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id) | 160 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr[ulp_num].id) |
156 | 161 | ||
157 | #define PAGES_REQUIRED(x) \ | 162 | #define PAGES_REQUIRED(x) \ |
158 | ((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE)) | 163 | ((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE)) |
159 | 164 | ||
160 | #define BEISCSI_MSI_NAME 20 /* size of msi_name string */ | 165 | #define BEISCSI_MSI_NAME 20 /* size of msi_name string */ |
161 | 166 | ||
167 | #define MEM_DESCR_OFFSET 8 | ||
168 | #define BEISCSI_DEFQ_HDR 1 | ||
169 | #define BEISCSI_DEFQ_DATA 0 | ||
162 | enum be_mem_enum { | 170 | enum be_mem_enum { |
163 | HWI_MEM_ADDN_CONTEXT, | 171 | HWI_MEM_ADDN_CONTEXT, |
164 | HWI_MEM_WRB, | 172 | HWI_MEM_WRB, |
165 | HWI_MEM_WRBH, | 173 | HWI_MEM_WRBH, |
166 | HWI_MEM_SGLH, | 174 | HWI_MEM_SGLH, |
167 | HWI_MEM_SGE, | 175 | HWI_MEM_SGE, |
168 | HWI_MEM_ASYNC_HEADER_BUF, /* 5 */ | 176 | HWI_MEM_TEMPLATE_HDR_ULP0, |
169 | HWI_MEM_ASYNC_DATA_BUF, | 177 | HWI_MEM_ASYNC_HEADER_BUF_ULP0, /* 6 */ |
170 | HWI_MEM_ASYNC_HEADER_RING, | 178 | HWI_MEM_ASYNC_DATA_BUF_ULP0, |
171 | HWI_MEM_ASYNC_DATA_RING, | 179 | HWI_MEM_ASYNC_HEADER_RING_ULP0, |
172 | HWI_MEM_ASYNC_HEADER_HANDLE, | 180 | HWI_MEM_ASYNC_DATA_RING_ULP0, |
173 | HWI_MEM_ASYNC_DATA_HANDLE, /* 10 */ | 181 | HWI_MEM_ASYNC_HEADER_HANDLE_ULP0, |
174 | HWI_MEM_ASYNC_PDU_CONTEXT, | 182 | HWI_MEM_ASYNC_DATA_HANDLE_ULP0, /* 11 */ |
183 | HWI_MEM_ASYNC_PDU_CONTEXT_ULP0, | ||
184 | HWI_MEM_TEMPLATE_HDR_ULP1, | ||
185 | HWI_MEM_ASYNC_HEADER_BUF_ULP1, /* 14 */ | ||
186 | HWI_MEM_ASYNC_DATA_BUF_ULP1, | ||
187 | HWI_MEM_ASYNC_HEADER_RING_ULP1, | ||
188 | HWI_MEM_ASYNC_DATA_RING_ULP1, | ||
189 | HWI_MEM_ASYNC_HEADER_HANDLE_ULP1, | ||
190 | HWI_MEM_ASYNC_DATA_HANDLE_ULP1, /* 19 */ | ||
191 | HWI_MEM_ASYNC_PDU_CONTEXT_ULP1, | ||
175 | ISCSI_MEM_GLOBAL_HEADER, | 192 | ISCSI_MEM_GLOBAL_HEADER, |
176 | SE_MEM_MAX | 193 | SE_MEM_MAX |
177 | }; | 194 | }; |
@@ -266,9 +283,49 @@ struct invalidate_command_table { | |||
266 | unsigned short cid; | 283 | unsigned short cid; |
267 | } __packed; | 284 | } __packed; |
268 | 285 | ||
286 | #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ | ||
287 | (phwi_ctrlr->wrb_context[cri].ulp_num) | ||
288 | struct hwi_wrb_context { | ||
289 | struct list_head wrb_handle_list; | ||
290 | struct list_head wrb_handle_drvr_list; | ||
291 | struct wrb_handle **pwrb_handle_base; | ||
292 | struct wrb_handle **pwrb_handle_basestd; | ||
293 | struct iscsi_wrb *plast_wrb; | ||
294 | unsigned short alloc_index; | ||
295 | unsigned short free_index; | ||
296 | unsigned short wrb_handles_available; | ||
297 | unsigned short cid; | ||
298 | uint8_t ulp_num; /* ULP to which CID binded */ | ||
299 | uint16_t register_set; | ||
300 | uint16_t doorbell_format; | ||
301 | uint32_t doorbell_offset; | ||
302 | }; | ||
303 | |||
304 | struct ulp_cid_info { | ||
305 | unsigned short *cid_array; | ||
306 | unsigned short avlbl_cids; | ||
307 | unsigned short cid_alloc; | ||
308 | unsigned short cid_free; | ||
309 | }; | ||
310 | |||
311 | #include "be.h" | ||
269 | #define chip_be2(phba) (phba->generation == BE_GEN2) | 312 | #define chip_be2(phba) (phba->generation == BE_GEN2) |
270 | #define chip_be3_r(phba) (phba->generation == BE_GEN3) | 313 | #define chip_be3_r(phba) (phba->generation == BE_GEN3) |
271 | #define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba))) | 314 | #define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba))) |
315 | |||
316 | #define BEISCSI_ULP0 0 | ||
317 | #define BEISCSI_ULP1 1 | ||
318 | #define BEISCSI_ULP_COUNT 2 | ||
319 | #define BEISCSI_ULP0_LOADED 0x01 | ||
320 | #define BEISCSI_ULP1_LOADED 0x02 | ||
321 | |||
322 | #define BEISCSI_ULP_AVLBL_CID(phba, ulp_num) \ | ||
323 | (((struct ulp_cid_info *)phba->cid_array_info[ulp_num])->avlbl_cids) | ||
324 | #define BEISCSI_ULP0_AVLBL_CID(phba) \ | ||
325 | BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP0) | ||
326 | #define BEISCSI_ULP1_AVLBL_CID(phba) \ | ||
327 | BEISCSI_ULP_AVLBL_CID(phba, BEISCSI_ULP1) | ||
328 | |||
272 | struct beiscsi_hba { | 329 | struct beiscsi_hba { |
273 | struct hba_parameters params; | 330 | struct hba_parameters params; |
274 | struct hwi_controller *phwi_ctrlr; | 331 | struct hwi_controller *phwi_ctrlr; |
@@ -303,17 +360,15 @@ struct beiscsi_hba { | |||
303 | spinlock_t io_sgl_lock; | 360 | spinlock_t io_sgl_lock; |
304 | spinlock_t mgmt_sgl_lock; | 361 | spinlock_t mgmt_sgl_lock; |
305 | spinlock_t isr_lock; | 362 | spinlock_t isr_lock; |
363 | spinlock_t async_pdu_lock; | ||
306 | unsigned int age; | 364 | unsigned int age; |
307 | unsigned short avlbl_cids; | ||
308 | unsigned short cid_alloc; | ||
309 | unsigned short cid_free; | ||
310 | struct list_head hba_queue; | 365 | struct list_head hba_queue; |
311 | #define BE_MAX_SESSION 2048 | 366 | #define BE_MAX_SESSION 2048 |
312 | #define BE_SET_CID_TO_CRI(cri_index, cid) \ | 367 | #define BE_SET_CID_TO_CRI(cri_index, cid) \ |
313 | (phba->cid_to_cri_map[cid] = cri_index) | 368 | (phba->cid_to_cri_map[cid] = cri_index) |
314 | #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) | 369 | #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) |
315 | unsigned short cid_to_cri_map[BE_MAX_SESSION]; | 370 | unsigned short cid_to_cri_map[BE_MAX_SESSION]; |
316 | unsigned short *cid_array; | 371 | struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT]; |
317 | struct iscsi_endpoint **ep_array; | 372 | struct iscsi_endpoint **ep_array; |
318 | struct beiscsi_conn **conn_table; | 373 | struct beiscsi_conn **conn_table; |
319 | struct iscsi_boot_kset *boot_kset; | 374 | struct iscsi_boot_kset *boot_kset; |
@@ -325,20 +380,21 @@ struct beiscsi_hba { | |||
325 | * group together since they are used most frequently | 380 | * group together since they are used most frequently |
326 | * for cid to cri conversion | 381 | * for cid to cri conversion |
327 | */ | 382 | */ |
328 | unsigned int iscsi_cid_start; | ||
329 | unsigned int phys_port; | 383 | unsigned int phys_port; |
384 | unsigned int eqid_count; | ||
385 | unsigned int cqid_count; | ||
386 | unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; | ||
387 | #define BEISCSI_GET_CID_COUNT(phba, ulp_num) \ | ||
388 | (phba->fw_config.iscsi_cid_count[ulp_num]) | ||
389 | unsigned int iscsi_cid_count[BEISCSI_ULP_COUNT]; | ||
390 | unsigned int iscsi_icd_count[BEISCSI_ULP_COUNT]; | ||
391 | unsigned int iscsi_icd_start[BEISCSI_ULP_COUNT]; | ||
392 | unsigned int iscsi_chain_start[BEISCSI_ULP_COUNT]; | ||
393 | unsigned int iscsi_chain_count[BEISCSI_ULP_COUNT]; | ||
330 | 394 | ||
331 | unsigned int isr_offset; | ||
332 | unsigned int iscsi_icd_start; | ||
333 | unsigned int iscsi_cid_count; | ||
334 | unsigned int iscsi_icd_count; | ||
335 | unsigned int pci_function; | ||
336 | |||
337 | unsigned short cid_alloc; | ||
338 | unsigned short cid_free; | ||
339 | unsigned short avlbl_cids; | ||
340 | unsigned short iscsi_features; | 395 | unsigned short iscsi_features; |
341 | spinlock_t cid_lock; | 396 | uint16_t dual_ulp_aware; |
397 | unsigned long ulp_supported; | ||
342 | } fw_config; | 398 | } fw_config; |
343 | 399 | ||
344 | unsigned int state; | 400 | unsigned int state; |
@@ -346,6 +402,7 @@ struct beiscsi_hba { | |||
346 | bool ue_detected; | 402 | bool ue_detected; |
347 | struct delayed_work beiscsi_hw_check_task; | 403 | struct delayed_work beiscsi_hw_check_task; |
348 | 404 | ||
405 | bool mac_addr_set; | ||
349 | u8 mac_address[ETH_ALEN]; | 406 | u8 mac_address[ETH_ALEN]; |
350 | char fw_ver_str[BEISCSI_VER_STRLEN]; | 407 | char fw_ver_str[BEISCSI_VER_STRLEN]; |
351 | char wq_name[20]; | 408 | char wq_name[20]; |
@@ -374,6 +431,7 @@ struct beiscsi_conn { | |||
374 | struct iscsi_conn *conn; | 431 | struct iscsi_conn *conn; |
375 | struct beiscsi_hba *phba; | 432 | struct beiscsi_hba *phba; |
376 | u32 exp_statsn; | 433 | u32 exp_statsn; |
434 | u32 doorbell_offset; | ||
377 | u32 beiscsi_conn_cid; | 435 | u32 beiscsi_conn_cid; |
378 | struct beiscsi_endpoint *ep; | 436 | struct beiscsi_endpoint *ep; |
379 | unsigned short login_in_progress; | 437 | unsigned short login_in_progress; |
@@ -474,7 +532,7 @@ struct amap_iscsi_sge { | |||
474 | }; | 532 | }; |
475 | 533 | ||
476 | struct beiscsi_offload_params { | 534 | struct beiscsi_offload_params { |
477 | u32 dw[5]; | 535 | u32 dw[6]; |
478 | }; | 536 | }; |
479 | 537 | ||
480 | #define OFFLD_PARAMS_ERL 0x00000003 | 538 | #define OFFLD_PARAMS_ERL 0x00000003 |
@@ -504,6 +562,7 @@ struct amap_beiscsi_offload_params { | |||
504 | u8 max_r2t[16]; | 562 | u8 max_r2t[16]; |
505 | u8 pad[8]; | 563 | u8 pad[8]; |
506 | u8 exp_statsn[32]; | 564 | u8 exp_statsn[32]; |
565 | u8 max_recv_data_segment_length[32]; | ||
507 | }; | 566 | }; |
508 | 567 | ||
509 | /* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | 568 | /* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, |
@@ -567,7 +626,8 @@ struct hwi_async_pdu_context { | |||
567 | 626 | ||
568 | unsigned int buffer_size; | 627 | unsigned int buffer_size; |
569 | unsigned int num_entries; | 628 | unsigned int num_entries; |
570 | 629 | #define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid]) | |
630 | unsigned short cid_to_async_cri_map[BE_MAX_SESSION]; | ||
571 | /** | 631 | /** |
572 | * This is a varying size list! Do not add anything | 632 | * This is a varying size list! Do not add anything |
573 | * after this entry!! | 633 | * after this entry!! |
@@ -885,30 +945,32 @@ struct amap_iscsi_target_context_update_wrb_v2 { | |||
885 | u8 first_burst_length[24]; /* DWORD 3 */ | 945 | u8 first_burst_length[24]; /* DWORD 3 */ |
886 | u8 rsvd3[8]; /* DOWRD 3 */ | 946 | u8 rsvd3[8]; /* DOWRD 3 */ |
887 | u8 max_r2t[16]; /* DWORD 4 */ | 947 | u8 max_r2t[16]; /* DWORD 4 */ |
888 | u8 rsvd4[10]; /* DWORD 4 */ | 948 | u8 rsvd4; /* DWORD 4 */ |
889 | u8 hde; /* DWORD 4 */ | 949 | u8 hde; /* DWORD 4 */ |
890 | u8 dde; /* DWORD 4 */ | 950 | u8 dde; /* DWORD 4 */ |
891 | u8 erl[2]; /* DWORD 4 */ | 951 | u8 erl[2]; /* DWORD 4 */ |
952 | u8 rsvd5[6]; /* DWORD 4 */ | ||
892 | u8 imd; /* DWORD 4 */ | 953 | u8 imd; /* DWORD 4 */ |
893 | u8 ir2t; /* DWORD 4 */ | 954 | u8 ir2t; /* DWORD 4 */ |
955 | u8 rsvd6[3]; /* DWORD 4 */ | ||
894 | u8 stat_sn[32]; /* DWORD 5 */ | 956 | u8 stat_sn[32]; /* DWORD 5 */ |
895 | u8 rsvd5[32]; /* DWORD 6 */ | 957 | u8 rsvd7[32]; /* DWORD 6 */ |
896 | u8 rsvd6[32]; /* DWORD 7 */ | 958 | u8 rsvd8[32]; /* DWORD 7 */ |
897 | u8 max_recv_dataseg_len[24]; /* DWORD 8 */ | 959 | u8 max_recv_dataseg_len[24]; /* DWORD 8 */ |
898 | u8 rsvd7[8]; /* DWORD 8 */ | 960 | u8 rsvd9[8]; /* DWORD 8 */ |
899 | u8 rsvd8[32]; /* DWORD 9 */ | 961 | u8 rsvd10[32]; /* DWORD 9 */ |
900 | u8 rsvd9[32]; /* DWORD 10 */ | 962 | u8 rsvd11[32]; /* DWORD 10 */ |
901 | u8 max_cxns[16]; /* DWORD 11 */ | 963 | u8 max_cxns[16]; /* DWORD 11 */ |
902 | u8 rsvd10[11]; /* DWORD 11*/ | 964 | u8 rsvd12[11]; /* DWORD 11*/ |
903 | u8 invld; /* DWORD 11 */ | 965 | u8 invld; /* DWORD 11 */ |
904 | u8 rsvd11;/* DWORD 11*/ | 966 | u8 rsvd13;/* DWORD 11*/ |
905 | u8 dmsg; /* DWORD 11 */ | 967 | u8 dmsg; /* DWORD 11 */ |
906 | u8 data_seq_inorder; /* DWORD 11 */ | 968 | u8 data_seq_inorder; /* DWORD 11 */ |
907 | u8 pdu_seq_inorder; /* DWORD 11 */ | 969 | u8 pdu_seq_inorder; /* DWORD 11 */ |
908 | u8 rsvd12[32]; /*DWORD 12 */ | 970 | u8 rsvd14[32]; /*DWORD 12 */ |
909 | u8 rsvd13[32]; /* DWORD 13 */ | 971 | u8 rsvd15[32]; /* DWORD 13 */ |
910 | u8 rsvd14[32]; /* DWORD 14 */ | 972 | u8 rsvd16[32]; /* DWORD 14 */ |
911 | u8 rsvd15[32]; /* DWORD 15 */ | 973 | u8 rsvd17[32]; /* DWORD 15 */ |
912 | } __packed; | 974 | } __packed; |
913 | 975 | ||
914 | 976 | ||
@@ -919,6 +981,10 @@ struct be_ring { | |||
919 | u32 cidx; /* consumer index */ | 981 | u32 cidx; /* consumer index */ |
920 | u32 pidx; /* producer index -- not used by most rings */ | 982 | u32 pidx; /* producer index -- not used by most rings */ |
921 | u32 item_size; /* size in bytes of one object */ | 983 | u32 item_size; /* size in bytes of one object */ |
984 | u8 ulp_num; /* ULP to which CID binded */ | ||
985 | u16 register_set; | ||
986 | u16 doorbell_format; | ||
987 | u32 doorbell_offset; | ||
922 | 988 | ||
923 | void *va; /* The virtual address of the ring. This | 989 | void *va; /* The virtual address of the ring. This |
924 | * should be last to allow 32 & 64 bit debugger | 990 | * should be last to allow 32 & 64 bit debugger |
@@ -926,18 +992,6 @@ struct be_ring { | |||
926 | */ | 992 | */ |
927 | }; | 993 | }; |
928 | 994 | ||
929 | struct hwi_wrb_context { | ||
930 | struct list_head wrb_handle_list; | ||
931 | struct list_head wrb_handle_drvr_list; | ||
932 | struct wrb_handle **pwrb_handle_base; | ||
933 | struct wrb_handle **pwrb_handle_basestd; | ||
934 | struct iscsi_wrb *plast_wrb; | ||
935 | unsigned short alloc_index; | ||
936 | unsigned short free_index; | ||
937 | unsigned short wrb_handles_available; | ||
938 | unsigned short cid; | ||
939 | }; | ||
940 | |||
941 | struct hwi_controller { | 995 | struct hwi_controller { |
942 | struct list_head io_sgl_list; | 996 | struct list_head io_sgl_list; |
943 | struct list_head eh_sgl_list; | 997 | struct list_head eh_sgl_list; |
@@ -946,8 +1000,8 @@ struct hwi_controller { | |||
946 | 1000 | ||
947 | struct hwi_wrb_context *wrb_context; | 1001 | struct hwi_wrb_context *wrb_context; |
948 | struct mcc_wrb *pmcc_wrb_base; | 1002 | struct mcc_wrb *pmcc_wrb_base; |
949 | struct be_ring default_pdu_hdr; | 1003 | struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT]; |
950 | struct be_ring default_pdu_data; | 1004 | struct be_ring default_pdu_data[BEISCSI_ULP_COUNT]; |
951 | struct hwi_context_memory *phwi_ctxt; | 1005 | struct hwi_context_memory *phwi_ctxt; |
952 | }; | 1006 | }; |
953 | 1007 | ||
@@ -978,11 +1032,10 @@ struct hwi_context_memory { | |||
978 | struct be_eq_obj be_eq[MAX_CPUS]; | 1032 | struct be_eq_obj be_eq[MAX_CPUS]; |
979 | struct be_queue_info be_cq[MAX_CPUS - 1]; | 1033 | struct be_queue_info be_cq[MAX_CPUS - 1]; |
980 | 1034 | ||
981 | struct be_queue_info be_def_hdrq; | ||
982 | struct be_queue_info be_def_dataq; | ||
983 | |||
984 | struct be_queue_info *be_wrbq; | 1035 | struct be_queue_info *be_wrbq; |
985 | struct hwi_async_pdu_context *pasync_ctx; | 1036 | struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT]; |
1037 | struct be_queue_info be_def_dataq[BEISCSI_ULP_COUNT]; | ||
1038 | struct hwi_async_pdu_context *pasync_ctx[BEISCSI_ULP_COUNT]; | ||
986 | }; | 1039 | }; |
987 | 1040 | ||
988 | /* Logging related definitions */ | 1041 | /* Logging related definitions */ |
@@ -992,6 +1045,7 @@ struct hwi_context_memory { | |||
992 | #define BEISCSI_LOG_EH 0x0008 /* Error Handler */ | 1045 | #define BEISCSI_LOG_EH 0x0008 /* Error Handler */ |
993 | #define BEISCSI_LOG_IO 0x0010 /* IO Code Path */ | 1046 | #define BEISCSI_LOG_IO 0x0010 /* IO Code Path */ |
994 | #define BEISCSI_LOG_CONFIG 0x0020 /* CONFIG Code Path */ | 1047 | #define BEISCSI_LOG_CONFIG 0x0020 /* CONFIG Code Path */ |
1048 | #define BEISCSI_LOG_ISCSI 0x0040 /* SCSI/iSCSI Protocol related Logs */ | ||
995 | 1049 | ||
996 | #define beiscsi_log(phba, level, mask, fmt, arg...) \ | 1050 | #define beiscsi_log(phba, level, mask, fmt, arg...) \ |
997 | do { \ | 1051 | do { \ |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 245a9595a93a..b2fcac78feaa 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -278,6 +278,18 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, | |||
278 | return tag; | 278 | return tag; |
279 | } | 279 | } |
280 | 280 | ||
281 | /** | ||
282 | * mgmt_get_fw_config()- Get the FW config for the function | ||
283 | * @ctrl: ptr to Ctrl Info | ||
284 | * @phba: ptr to the dev priv structure | ||
285 | * | ||
286 | * Get the FW config and resources available for the function. | ||
287 | * The resources are created based on the count received here. | ||
288 | * | ||
289 | * return | ||
290 | * Success: 0 | ||
291 | * Failure: Non-Zero Value | ||
292 | **/ | ||
281 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | 293 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, |
282 | struct beiscsi_hba *phba) | 294 | struct beiscsi_hba *phba) |
283 | { | 295 | { |
@@ -291,31 +303,79 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | |||
291 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 303 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
292 | 304 | ||
293 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 305 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
294 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); | 306 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, |
307 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
295 | status = be_mbox_notify(ctrl); | 308 | status = be_mbox_notify(ctrl); |
296 | if (!status) { | 309 | if (!status) { |
310 | uint8_t ulp_num = 0; | ||
297 | struct be_fw_cfg *pfw_cfg; | 311 | struct be_fw_cfg *pfw_cfg; |
298 | pfw_cfg = req; | 312 | pfw_cfg = req; |
313 | |||
314 | if (!is_chip_be2_be3r(phba)) { | ||
315 | phba->fw_config.eqid_count = pfw_cfg->eqid_count; | ||
316 | phba->fw_config.cqid_count = pfw_cfg->cqid_count; | ||
317 | |||
318 | beiscsi_log(phba, KERN_INFO, | ||
319 | BEISCSI_LOG_INIT, | ||
320 | "BG_%d : EQ_Count : %d CQ_Count : %d\n", | ||
321 | phba->fw_config.eqid_count, | ||
322 | phba->fw_config.cqid_count); | ||
323 | } | ||
324 | |||
325 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
326 | if (pfw_cfg->ulp[ulp_num].ulp_mode & | ||
327 | BEISCSI_ULP_ISCSI_INI_MODE) | ||
328 | set_bit(ulp_num, | ||
329 | &phba->fw_config.ulp_supported); | ||
330 | |||
299 | phba->fw_config.phys_port = pfw_cfg->phys_port; | 331 | phba->fw_config.phys_port = pfw_cfg->phys_port; |
300 | phba->fw_config.iscsi_icd_start = | 332 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
301 | pfw_cfg->ulp[0].icd_base; | 333 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
302 | phba->fw_config.iscsi_icd_count = | 334 | |
303 | pfw_cfg->ulp[0].icd_count; | 335 | phba->fw_config.iscsi_cid_start[ulp_num] = |
304 | phba->fw_config.iscsi_cid_start = | 336 | pfw_cfg->ulp[ulp_num].sq_base; |
305 | pfw_cfg->ulp[0].sq_base; | 337 | phba->fw_config.iscsi_cid_count[ulp_num] = |
306 | phba->fw_config.iscsi_cid_count = | 338 | pfw_cfg->ulp[ulp_num].sq_count; |
307 | pfw_cfg->ulp[0].sq_count; | 339 | |
308 | if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { | 340 | phba->fw_config.iscsi_icd_start[ulp_num] = |
309 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 341 | pfw_cfg->ulp[ulp_num].icd_base; |
310 | "BG_%d : FW reported MAX CXNS as %d\t" | 342 | phba->fw_config.iscsi_icd_count[ulp_num] = |
311 | "Max Supported = %d.\n", | 343 | pfw_cfg->ulp[ulp_num].icd_count; |
312 | phba->fw_config.iscsi_cid_count, | 344 | |
313 | BE2_MAX_SESSIONS); | 345 | phba->fw_config.iscsi_chain_start[ulp_num] = |
314 | phba->fw_config.iscsi_cid_count = BE2_MAX_SESSIONS / 2; | 346 | pfw_cfg->chain_icd[ulp_num].chain_base; |
347 | phba->fw_config.iscsi_chain_count[ulp_num] = | ||
348 | pfw_cfg->chain_icd[ulp_num].chain_count; | ||
349 | |||
350 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
351 | "BG_%d : Function loaded on ULP : %d\n" | ||
352 | "\tiscsi_cid_count : %d\n" | ||
353 | "\tiscsi_cid_start : %d\n" | ||
354 | "\t iscsi_icd_count : %d\n" | ||
355 | "\t iscsi_icd_start : %d\n", | ||
356 | ulp_num, | ||
357 | phba->fw_config. | ||
358 | iscsi_cid_count[ulp_num], | ||
359 | phba->fw_config. | ||
360 | iscsi_cid_start[ulp_num], | ||
361 | phba->fw_config. | ||
362 | iscsi_icd_count[ulp_num], | ||
363 | phba->fw_config. | ||
364 | iscsi_icd_start[ulp_num]); | ||
365 | } | ||
315 | } | 366 | } |
367 | |||
368 | phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode & | ||
369 | BEISCSI_FUNC_DUA_MODE); | ||
370 | |||
371 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
372 | "BG_%d : DUA Mode : 0x%x\n", | ||
373 | phba->fw_config.dual_ulp_aware); | ||
374 | |||
316 | } else { | 375 | } else { |
317 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | 376 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
318 | "BG_%d : Failed in mgmt_get_fw_config\n"); | 377 | "BG_%d : Failed in mgmt_get_fw_config\n"); |
378 | status = -EINVAL; | ||
319 | } | 379 | } |
320 | 380 | ||
321 | spin_unlock(&ctrl->mbox_lock); | 381 | spin_unlock(&ctrl->mbox_lock); |
@@ -448,7 +508,16 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, | |||
448 | return tag; | 508 | return tag; |
449 | } | 509 | } |
450 | 510 | ||
451 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | 511 | /** |
512 | * mgmt_epfw_cleanup()- Inform FW to cleanup data structures. | ||
513 | * @phba: pointer to dev priv structure | ||
514 | * @ulp_num: ULP number. | ||
515 | * | ||
516 | * return | ||
517 | * Success: 0 | ||
518 | * Failure: Non-Zero Value | ||
519 | **/ | ||
520 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num) | ||
452 | { | 521 | { |
453 | struct be_ctrl_info *ctrl = &phba->ctrl; | 522 | struct be_ctrl_info *ctrl = &phba->ctrl; |
454 | struct be_mcc_wrb *wrb = wrb_from_mccq(phba); | 523 | struct be_mcc_wrb *wrb = wrb_from_mccq(phba); |
@@ -462,9 +531,9 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | |||
462 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 531 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, |
463 | OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | 532 | OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); |
464 | 533 | ||
465 | req->chute = chute; | 534 | req->chute = (1 << ulp_num); |
466 | req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba)); | 535 | req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, ulp_num)); |
467 | req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba)); | 536 | req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, ulp_num)); |
468 | 537 | ||
469 | status = be_mcc_notify_wait(phba); | 538 | status = be_mcc_notify_wait(phba); |
470 | if (status) | 539 | if (status) |
@@ -585,6 +654,16 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, | |||
585 | return tag; | 654 | return tag; |
586 | } | 655 | } |
587 | 656 | ||
657 | /** | ||
658 | * mgmt_open_connection()- Establish a TCP CXN | ||
659 | * @dst_addr: Destination Address | ||
660 | * @beiscsi_ep: ptr to device endpoint struct | ||
661 | * @nonemb_cmd: ptr to memory allocated for command | ||
662 | * | ||
663 | * return | ||
664 | * Success: Tag number of the MBX Command issued | ||
665 | * Failure: Error code | ||
666 | **/ | ||
588 | int mgmt_open_connection(struct beiscsi_hba *phba, | 667 | int mgmt_open_connection(struct beiscsi_hba *phba, |
589 | struct sockaddr *dst_addr, | 668 | struct sockaddr *dst_addr, |
590 | struct beiscsi_endpoint *beiscsi_ep, | 669 | struct beiscsi_endpoint *beiscsi_ep, |
@@ -602,14 +681,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba, | |||
602 | struct phys_addr template_address = { 0, 0 }; | 681 | struct phys_addr template_address = { 0, 0 }; |
603 | struct phys_addr *ptemplate_address; | 682 | struct phys_addr *ptemplate_address; |
604 | unsigned int tag = 0; | 683 | unsigned int tag = 0; |
605 | unsigned int i; | 684 | unsigned int i, ulp_num; |
606 | unsigned short cid = beiscsi_ep->ep_cid; | 685 | unsigned short cid = beiscsi_ep->ep_cid; |
607 | struct be_sge *sge; | 686 | struct be_sge *sge; |
608 | 687 | ||
609 | phwi_ctrlr = phba->phwi_ctrlr; | 688 | phwi_ctrlr = phba->phwi_ctrlr; |
610 | phwi_context = phwi_ctrlr->phwi_ctxt; | 689 | phwi_context = phwi_ctrlr->phwi_ctxt; |
611 | def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba); | 690 | |
612 | def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); | 691 | ulp_num = phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID(cid)].ulp_num; |
692 | |||
693 | def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba, ulp_num); | ||
694 | def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba, ulp_num); | ||
613 | 695 | ||
614 | ptemplate_address = &template_address; | 696 | ptemplate_address = &template_address; |
615 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); | 697 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); |
@@ -748,11 +830,14 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, | |||
748 | 830 | ||
749 | rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); | 831 | rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); |
750 | if (rc) { | 832 | if (rc) { |
833 | /* Check if the IOCTL needs to be re-issued */ | ||
834 | if (rc == -EAGAIN) | ||
835 | return rc; | ||
836 | |||
751 | beiscsi_log(phba, KERN_ERR, | 837 | beiscsi_log(phba, KERN_ERR, |
752 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 838 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
753 | "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); | 839 | "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); |
754 | 840 | ||
755 | rc = -EIO; | ||
756 | goto free_cmd; | 841 | goto free_cmd; |
757 | } | 842 | } |
758 | 843 | ||
@@ -861,7 +946,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
861 | uint32_t boot_proto) | 946 | uint32_t boot_proto) |
862 | { | 947 | { |
863 | struct be_cmd_get_def_gateway_resp gtway_addr_set; | 948 | struct be_cmd_get_def_gateway_resp gtway_addr_set; |
864 | struct be_cmd_get_if_info_resp if_info; | 949 | struct be_cmd_get_if_info_resp *if_info; |
865 | struct be_cmd_set_dhcp_req *dhcpreq; | 950 | struct be_cmd_set_dhcp_req *dhcpreq; |
866 | struct be_cmd_rel_dhcp_req *reldhcp; | 951 | struct be_cmd_rel_dhcp_req *reldhcp; |
867 | struct be_dma_mem nonemb_cmd; | 952 | struct be_dma_mem nonemb_cmd; |
@@ -872,16 +957,17 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
872 | if (mgmt_get_all_if_id(phba)) | 957 | if (mgmt_get_all_if_id(phba)) |
873 | return -EIO; | 958 | return -EIO; |
874 | 959 | ||
875 | memset(&if_info, 0, sizeof(if_info)); | ||
876 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | 960 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? |
877 | BE2_IPV6 : BE2_IPV4 ; | 961 | BE2_IPV6 : BE2_IPV4 ; |
878 | 962 | ||
879 | rc = mgmt_get_if_info(phba, ip_type, &if_info); | 963 | rc = mgmt_get_if_info(phba, ip_type, &if_info); |
880 | if (rc) | 964 | if (rc) { |
965 | kfree(if_info); | ||
881 | return rc; | 966 | return rc; |
967 | } | ||
882 | 968 | ||
883 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | 969 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { |
884 | if (if_info.dhcp_state) { | 970 | if (if_info->dhcp_state) { |
885 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 971 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
886 | "BG_%d : DHCP Already Enabled\n"); | 972 | "BG_%d : DHCP Already Enabled\n"); |
887 | return 0; | 973 | return 0; |
@@ -894,9 +980,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
894 | IP_V6_LEN : IP_V4_LEN; | 980 | IP_V6_LEN : IP_V4_LEN; |
895 | 981 | ||
896 | } else { | 982 | } else { |
897 | if (if_info.dhcp_state) { | 983 | if (if_info->dhcp_state) { |
898 | 984 | ||
899 | memset(&if_info, 0, sizeof(if_info)); | 985 | memset(if_info, 0, sizeof(*if_info)); |
900 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 986 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
901 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | 987 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, |
902 | sizeof(*reldhcp)); | 988 | sizeof(*reldhcp)); |
@@ -919,8 +1005,8 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
919 | } | 1005 | } |
920 | 1006 | ||
921 | /* Delete the Static IP Set */ | 1007 | /* Delete the Static IP Set */ |
922 | if (if_info.ip_addr.addr[0]) { | 1008 | if (if_info->ip_addr.addr[0]) { |
923 | rc = mgmt_static_ip_modify(phba, &if_info, ip_param, NULL, | 1009 | rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, |
924 | IP_ACTION_DEL); | 1010 | IP_ACTION_DEL); |
925 | if (rc) | 1011 | if (rc) |
926 | return rc; | 1012 | return rc; |
@@ -966,7 +1052,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, | |||
966 | 1052 | ||
967 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | 1053 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
968 | } else { | 1054 | } else { |
969 | return mgmt_static_ip_modify(phba, &if_info, ip_param, | 1055 | return mgmt_static_ip_modify(phba, if_info, ip_param, |
970 | subnet_param, IP_ACTION_ADD); | 1056 | subnet_param, IP_ACTION_ADD); |
971 | } | 1057 | } |
972 | 1058 | ||
@@ -1031,27 +1117,64 @@ int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | |||
1031 | } | 1117 | } |
1032 | 1118 | ||
1033 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 1119 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, |
1034 | struct be_cmd_get_if_info_resp *if_info) | 1120 | struct be_cmd_get_if_info_resp **if_info) |
1035 | { | 1121 | { |
1036 | struct be_cmd_get_if_info_req *req; | 1122 | struct be_cmd_get_if_info_req *req; |
1037 | struct be_dma_mem nonemb_cmd; | 1123 | struct be_dma_mem nonemb_cmd; |
1124 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); | ||
1038 | int rc; | 1125 | int rc; |
1039 | 1126 | ||
1040 | if (mgmt_get_all_if_id(phba)) | 1127 | if (mgmt_get_all_if_id(phba)) |
1041 | return -EIO; | 1128 | return -EIO; |
1042 | 1129 | ||
1043 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 1130 | do { |
1044 | OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, | 1131 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
1045 | sizeof(*if_info)); | 1132 | OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO, |
1046 | if (rc) | 1133 | ioctl_size); |
1047 | return rc; | 1134 | if (rc) |
1135 | return rc; | ||
1048 | 1136 | ||
1049 | req = nonemb_cmd.va; | 1137 | req = nonemb_cmd.va; |
1050 | req->interface_hndl = phba->interface_handle; | 1138 | req->interface_hndl = phba->interface_handle; |
1051 | req->ip_type = ip_type; | 1139 | req->ip_type = ip_type; |
1140 | |||
1141 | /* Allocate memory for if_info */ | ||
1142 | *if_info = kzalloc(ioctl_size, GFP_KERNEL); | ||
1143 | if (!*if_info) { | ||
1144 | beiscsi_log(phba, KERN_ERR, | ||
1145 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
1146 | "BG_%d : Memory Allocation Failure\n"); | ||
1147 | |||
1148 | /* Free the DMA memory for the IOCTL issuing */ | ||
1149 | pci_free_consistent(phba->ctrl.pdev, | ||
1150 | nonemb_cmd.size, | ||
1151 | nonemb_cmd.va, | ||
1152 | nonemb_cmd.dma); | ||
1153 | return -ENOMEM; | ||
1154 | } | ||
1155 | |||
1156 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, *if_info, | ||
1157 | ioctl_size); | ||
1158 | |||
1159 | /* Check if the error is because of Insufficent_Buffer */ | ||
1160 | if (rc == -EAGAIN) { | ||
1161 | |||
1162 | /* Get the new memory size */ | ||
1163 | ioctl_size = ((struct be_cmd_resp_hdr *) | ||
1164 | nonemb_cmd.va)->actual_resp_len; | ||
1165 | ioctl_size += sizeof(struct be_cmd_req_hdr); | ||
1052 | 1166 | ||
1053 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, if_info, | 1167 | /* Free the previous allocated DMA memory */ |
1054 | sizeof(*if_info)); | 1168 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, |
1169 | nonemb_cmd.va, | ||
1170 | nonemb_cmd.dma); | ||
1171 | |||
1172 | /* Free the virtual memory */ | ||
1173 | kfree(*if_info); | ||
1174 | } else | ||
1175 | break; | ||
1176 | } while (true); | ||
1177 | return rc; | ||
1055 | } | 1178 | } |
1056 | 1179 | ||
1057 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, | 1180 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, |
@@ -1281,7 +1404,7 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, | |||
1281 | } | 1404 | } |
1282 | 1405 | ||
1283 | /** | 1406 | /** |
1284 | * beiscsi_active_cid_disp()- Display Sessions Active | 1407 | * beiscsi_active_session_disp()- Display Sessions Active |
1285 | * @dev: ptr to device not used. | 1408 | * @dev: ptr to device not used. |
1286 | * @attr: device attribute, not used. | 1409 | * @attr: device attribute, not used. |
1287 | * @buf: contains formatted text Session Count | 1410 | * @buf: contains formatted text Session Count |
@@ -1290,14 +1413,56 @@ beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, | |||
1290 | * size of the formatted string | 1413 | * size of the formatted string |
1291 | **/ | 1414 | **/ |
1292 | ssize_t | 1415 | ssize_t |
1293 | beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr, | 1416 | beiscsi_active_session_disp(struct device *dev, struct device_attribute *attr, |
1294 | char *buf) | 1417 | char *buf) |
1295 | { | 1418 | { |
1296 | struct Scsi_Host *shost = class_to_shost(dev); | 1419 | struct Scsi_Host *shost = class_to_shost(dev); |
1297 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 1420 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
1421 | uint16_t avlbl_cids = 0, ulp_num, len = 0, total_cids = 0; | ||
1422 | |||
1423 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
1424 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { | ||
1425 | avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num); | ||
1426 | total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num); | ||
1427 | len += snprintf(buf+len, PAGE_SIZE - len, | ||
1428 | "ULP%d : %d\n", ulp_num, | ||
1429 | (total_cids - avlbl_cids)); | ||
1430 | } else | ||
1431 | len += snprintf(buf+len, PAGE_SIZE - len, | ||
1432 | "ULP%d : %d\n", ulp_num, 0); | ||
1433 | } | ||
1298 | 1434 | ||
1299 | return snprintf(buf, PAGE_SIZE, "%d\n", | 1435 | return len; |
1300 | (phba->params.cxns_per_ctrl - phba->avlbl_cids)); | 1436 | } |
1437 | |||
1438 | /** | ||
1439 | * beiscsi_free_session_disp()- Display Avaliable Session | ||
1440 | * @dev: ptr to device not used. | ||
1441 | * @attr: device attribute, not used. | ||
1442 | * @buf: contains formatted text Session Count | ||
1443 | * | ||
1444 | * return | ||
1445 | * size of the formatted string | ||
1446 | **/ | ||
1447 | ssize_t | ||
1448 | beiscsi_free_session_disp(struct device *dev, struct device_attribute *attr, | ||
1449 | char *buf) | ||
1450 | { | ||
1451 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1452 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
1453 | uint16_t ulp_num, len = 0; | ||
1454 | |||
1455 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
1456 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) | ||
1457 | len += snprintf(buf+len, PAGE_SIZE - len, | ||
1458 | "ULP%d : %d\n", ulp_num, | ||
1459 | BEISCSI_ULP_AVLBL_CID(phba, ulp_num)); | ||
1460 | else | ||
1461 | len += snprintf(buf+len, PAGE_SIZE - len, | ||
1462 | "ULP%d : %d\n", ulp_num, 0); | ||
1463 | } | ||
1464 | |||
1465 | return len; | ||
1301 | } | 1466 | } |
1302 | 1467 | ||
1303 | /** | 1468 | /** |
@@ -1338,6 +1503,25 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, | |||
1338 | } | 1503 | } |
1339 | } | 1504 | } |
1340 | 1505 | ||
1506 | /** | ||
1507 | * beiscsi_phys_port()- Display Physical Port Identifier | ||
1508 | * @dev: ptr to device not used. | ||
1509 | * @attr: device attribute, not used. | ||
1510 | * @buf: contains formatted text port identifier | ||
1511 | * | ||
1512 | * return | ||
1513 | * size of the formatted string | ||
1514 | **/ | ||
1515 | ssize_t | ||
1516 | beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr, | ||
1517 | char *buf) | ||
1518 | { | ||
1519 | struct Scsi_Host *shost = class_to_shost(dev); | ||
1520 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
1521 | |||
1522 | return snprintf(buf, PAGE_SIZE, "Port Identifier : %d\n", | ||
1523 | phba->fw_config.phys_port); | ||
1524 | } | ||
1341 | 1525 | ||
1342 | void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, | 1526 | void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, |
1343 | struct wrb_handle *pwrb_handle, | 1527 | struct wrb_handle *pwrb_handle, |
@@ -1411,10 +1595,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, | |||
1411 | 1595 | ||
1412 | memset(pwrb, 0, sizeof(*pwrb)); | 1596 | memset(pwrb, 0, sizeof(*pwrb)); |
1413 | 1597 | ||
1414 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
1415 | max_burst_length, pwrb, params->dw[offsetof | ||
1416 | (struct amap_beiscsi_offload_params, | ||
1417 | max_burst_length) / 32]); | ||
1418 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | 1598 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
1419 | max_burst_length, pwrb, params->dw[offsetof | 1599 | max_burst_length, pwrb, params->dw[offsetof |
1420 | (struct amap_beiscsi_offload_params, | 1600 | (struct amap_beiscsi_offload_params, |
@@ -1436,7 +1616,9 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, | |||
1436 | params->dw[offsetof(struct amap_beiscsi_offload_params, | 1616 | params->dw[offsetof(struct amap_beiscsi_offload_params, |
1437 | first_burst_length) / 32]); | 1617 | first_burst_length) / 32]); |
1438 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | 1618 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
1439 | max_recv_dataseg_len, pwrb, BEISCSI_MAX_RECV_DATASEG_LEN); | 1619 | max_recv_dataseg_len, pwrb, |
1620 | params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
1621 | max_recv_data_segment_length) / 32]); | ||
1440 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | 1622 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
1441 | max_cxns, pwrb, BEISCSI_MAX_CXNS); | 1623 | max_cxns, pwrb, BEISCSI_MAX_CXNS); |
1442 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, | 1624 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, erl, pwrb, |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 04af7e74fe48..01b8c97284c0 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -294,7 +294,7 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba, | |||
294 | struct be_cmd_get_nic_conf_resp *mac); | 294 | struct be_cmd_get_nic_conf_resp *mac); |
295 | 295 | ||
296 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 296 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, |
297 | struct be_cmd_get_if_info_resp *if_info); | 297 | struct be_cmd_get_if_info_resp **if_info); |
298 | 298 | ||
299 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | 299 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, |
300 | struct be_cmd_get_def_gateway_resp *gateway); | 300 | struct be_cmd_get_def_gateway_resp *gateway); |
@@ -315,12 +315,19 @@ ssize_t beiscsi_drvr_ver_disp(struct device *dev, | |||
315 | ssize_t beiscsi_fw_ver_disp(struct device *dev, | 315 | ssize_t beiscsi_fw_ver_disp(struct device *dev, |
316 | struct device_attribute *attr, char *buf); | 316 | struct device_attribute *attr, char *buf); |
317 | 317 | ||
318 | ssize_t beiscsi_active_cid_disp(struct device *dev, | 318 | ssize_t beiscsi_active_session_disp(struct device *dev, |
319 | struct device_attribute *attr, char *buf); | 319 | struct device_attribute *attr, char *buf); |
320 | 320 | ||
321 | ssize_t beiscsi_adap_family_disp(struct device *dev, | 321 | ssize_t beiscsi_adap_family_disp(struct device *dev, |
322 | struct device_attribute *attr, char *buf); | 322 | struct device_attribute *attr, char *buf); |
323 | 323 | ||
324 | |||
325 | ssize_t beiscsi_free_session_disp(struct device *dev, | ||
326 | struct device_attribute *attr, char *buf); | ||
327 | |||
328 | ssize_t beiscsi_phys_port_disp(struct device *dev, | ||
329 | struct device_attribute *attr, char *buf); | ||
330 | |||
324 | void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, | 331 | void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, |
325 | struct wrb_handle *pwrb_handle, | 332 | struct wrb_handle *pwrb_handle, |
326 | struct be_mem_descriptor *mem_descr); | 333 | struct be_mem_descriptor *mem_descr); |
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index d7ca9305ff45..1ebf3fb683e6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h | |||
@@ -64,7 +64,7 @@ | |||
64 | #include "bnx2fc_constants.h" | 64 | #include "bnx2fc_constants.h" |
65 | 65 | ||
66 | #define BNX2FC_NAME "bnx2fc" | 66 | #define BNX2FC_NAME "bnx2fc" |
67 | #define BNX2FC_VERSION "1.0.14" | 67 | #define BNX2FC_VERSION "2.4.1" |
68 | 68 | ||
69 | #define PFX "bnx2fc: " | 69 | #define PFX "bnx2fc: " |
70 | 70 | ||
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 69ac55495c1d..9b948505d118 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c | |||
@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); | |||
22 | 22 | ||
23 | #define DRV_MODULE_NAME "bnx2fc" | 23 | #define DRV_MODULE_NAME "bnx2fc" |
24 | #define DRV_MODULE_VERSION BNX2FC_VERSION | 24 | #define DRV_MODULE_VERSION BNX2FC_VERSION |
25 | #define DRV_MODULE_RELDATE "Mar 08, 2013" | 25 | #define DRV_MODULE_RELDATE "Sep 17, 2013" |
26 | 26 | ||
27 | 27 | ||
28 | static char version[] = | 28 | static char version[] = |
@@ -542,8 +542,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) | |||
542 | vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); | 542 | vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); |
543 | if (vn_port) { | 543 | if (vn_port) { |
544 | port = lport_priv(vn_port); | 544 | port = lport_priv(vn_port); |
545 | if (compare_ether_addr(port->data_src_addr, dest_mac) | 545 | if (!ether_addr_equal(port->data_src_addr, dest_mac)) { |
546 | != 0) { | ||
547 | BNX2FC_HBA_DBG(lport, "fpma mismatch\n"); | 546 | BNX2FC_HBA_DBG(lport, "fpma mismatch\n"); |
548 | put_cpu(); | 547 | put_cpu(); |
549 | kfree_skb(skb); | 548 | kfree_skb(skb); |
@@ -1381,6 +1380,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, | |||
1381 | return NULL; | 1380 | return NULL; |
1382 | } | 1381 | } |
1383 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | 1382 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); |
1383 | ctlr->cdev = ctlr_dev; | ||
1384 | interface = fcoe_ctlr_priv(ctlr); | 1384 | interface = fcoe_ctlr_priv(ctlr); |
1385 | dev_hold(netdev); | 1385 | dev_hold(netdev); |
1386 | kref_init(&interface->kref); | 1386 | kref_init(&interface->kref); |
@@ -2004,6 +2004,24 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) | |||
2004 | set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic); | 2004 | set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic); |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | /* Assumes rtnl_lock and the bnx2fc_dev_lock are already taken */ | ||
2008 | static int __bnx2fc_disable(struct fcoe_ctlr *ctlr) | ||
2009 | { | ||
2010 | struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr); | ||
2011 | |||
2012 | if (interface->enabled == true) { | ||
2013 | if (!ctlr->lp) { | ||
2014 | pr_err(PFX "__bnx2fc_disable: lport not found\n"); | ||
2015 | return -ENODEV; | ||
2016 | } else { | ||
2017 | interface->enabled = false; | ||
2018 | fcoe_ctlr_link_down(ctlr); | ||
2019 | fcoe_clean_pending_queue(ctlr->lp); | ||
2020 | } | ||
2021 | } | ||
2022 | return 0; | ||
2023 | } | ||
2024 | |||
2007 | /** | 2025 | /** |
2008 | * Deperecated: Use bnx2fc_enabled() | 2026 | * Deperecated: Use bnx2fc_enabled() |
2009 | */ | 2027 | */ |
@@ -2018,20 +2036,34 @@ static int bnx2fc_disable(struct net_device *netdev) | |||
2018 | 2036 | ||
2019 | interface = bnx2fc_interface_lookup(netdev); | 2037 | interface = bnx2fc_interface_lookup(netdev); |
2020 | ctlr = bnx2fc_to_ctlr(interface); | 2038 | ctlr = bnx2fc_to_ctlr(interface); |
2021 | if (!interface || !ctlr->lp) { | 2039 | |
2040 | if (!interface) { | ||
2022 | rc = -ENODEV; | 2041 | rc = -ENODEV; |
2023 | printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); | 2042 | pr_err(PFX "bnx2fc_disable: interface not found\n"); |
2024 | } else { | 2043 | } else { |
2025 | interface->enabled = false; | 2044 | rc = __bnx2fc_disable(ctlr); |
2026 | fcoe_ctlr_link_down(ctlr); | ||
2027 | fcoe_clean_pending_queue(ctlr->lp); | ||
2028 | } | 2045 | } |
2029 | |||
2030 | mutex_unlock(&bnx2fc_dev_lock); | 2046 | mutex_unlock(&bnx2fc_dev_lock); |
2031 | rtnl_unlock(); | 2047 | rtnl_unlock(); |
2032 | return rc; | 2048 | return rc; |
2033 | } | 2049 | } |
2034 | 2050 | ||
2051 | static int __bnx2fc_enable(struct fcoe_ctlr *ctlr) | ||
2052 | { | ||
2053 | struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr); | ||
2054 | |||
2055 | if (interface->enabled == false) { | ||
2056 | if (!ctlr->lp) { | ||
2057 | pr_err(PFX "__bnx2fc_enable: lport not found\n"); | ||
2058 | return -ENODEV; | ||
2059 | } else if (!bnx2fc_link_ok(ctlr->lp)) { | ||
2060 | fcoe_ctlr_link_up(ctlr); | ||
2061 | interface->enabled = true; | ||
2062 | } | ||
2063 | } | ||
2064 | return 0; | ||
2065 | } | ||
2066 | |||
2035 | /** | 2067 | /** |
2036 | * Deprecated: Use bnx2fc_enabled() | 2068 | * Deprecated: Use bnx2fc_enabled() |
2037 | */ | 2069 | */ |
@@ -2046,12 +2078,11 @@ static int bnx2fc_enable(struct net_device *netdev) | |||
2046 | 2078 | ||
2047 | interface = bnx2fc_interface_lookup(netdev); | 2079 | interface = bnx2fc_interface_lookup(netdev); |
2048 | ctlr = bnx2fc_to_ctlr(interface); | 2080 | ctlr = bnx2fc_to_ctlr(interface); |
2049 | if (!interface || !ctlr->lp) { | 2081 | if (!interface) { |
2050 | rc = -ENODEV; | 2082 | rc = -ENODEV; |
2051 | printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); | 2083 | pr_err(PFX "bnx2fc_enable: interface not found\n"); |
2052 | } else if (!bnx2fc_link_ok(ctlr->lp)) { | 2084 | } else { |
2053 | fcoe_ctlr_link_up(ctlr); | 2085 | rc = __bnx2fc_enable(ctlr); |
2054 | interface->enabled = true; | ||
2055 | } | 2086 | } |
2056 | 2087 | ||
2057 | mutex_unlock(&bnx2fc_dev_lock); | 2088 | mutex_unlock(&bnx2fc_dev_lock); |
@@ -2072,14 +2103,12 @@ static int bnx2fc_enable(struct net_device *netdev) | |||
2072 | static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) | 2103 | static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) |
2073 | { | 2104 | { |
2074 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev); | 2105 | struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev); |
2075 | struct fc_lport *lport = ctlr->lp; | ||
2076 | struct net_device *netdev = bnx2fc_netdev(lport); | ||
2077 | 2106 | ||
2078 | switch (cdev->enabled) { | 2107 | switch (cdev->enabled) { |
2079 | case FCOE_CTLR_ENABLED: | 2108 | case FCOE_CTLR_ENABLED: |
2080 | return bnx2fc_enable(netdev); | 2109 | return __bnx2fc_enable(ctlr); |
2081 | case FCOE_CTLR_DISABLED: | 2110 | case FCOE_CTLR_DISABLED: |
2082 | return bnx2fc_disable(netdev); | 2111 | return __bnx2fc_disable(ctlr); |
2083 | case FCOE_CTLR_UNUSED: | 2112 | case FCOE_CTLR_UNUSED: |
2084 | default: | 2113 | default: |
2085 | return -ENOTSUPP; | 2114 | return -ENOTSUPP; |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 575142e92d9c..ed880891cb7c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c | |||
@@ -1246,6 +1246,12 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
1246 | kref_put(&io_req->refcount, | 1246 | kref_put(&io_req->refcount, |
1247 | bnx2fc_cmd_release); /* drop timer hold */ | 1247 | bnx2fc_cmd_release); /* drop timer hold */ |
1248 | rc = bnx2fc_expl_logo(lport, io_req); | 1248 | rc = bnx2fc_expl_logo(lport, io_req); |
1249 | /* This only occurs when an task abort was requested while ABTS | ||
1250 | is in progress. Setting the IO_CLEANUP flag will skip the | ||
1251 | RRQ process in the case when the fw generated SCSI_CMD cmpl | ||
1252 | was a result from the ABTS request rather than the CLEANUP | ||
1253 | request */ | ||
1254 | set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags); | ||
1249 | goto out; | 1255 | goto out; |
1250 | } | 1256 | } |
1251 | 1257 | ||
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 694e13c45dfd..42e8624a9b9a 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c | |||
@@ -308,6 +308,8 @@ struct AdapterCtlBlk { | |||
308 | struct timer_list waiting_timer; | 308 | struct timer_list waiting_timer; |
309 | struct timer_list selto_timer; | 309 | struct timer_list selto_timer; |
310 | 310 | ||
311 | unsigned long last_reset; | ||
312 | |||
311 | u16 srb_count; | 313 | u16 srb_count; |
312 | 314 | ||
313 | u8 sel_timeout; | 315 | u8 sel_timeout; |
@@ -860,9 +862,9 @@ static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to) | |||
860 | init_timer(&acb->waiting_timer); | 862 | init_timer(&acb->waiting_timer); |
861 | acb->waiting_timer.function = waiting_timeout; | 863 | acb->waiting_timer.function = waiting_timeout; |
862 | acb->waiting_timer.data = (unsigned long) acb; | 864 | acb->waiting_timer.data = (unsigned long) acb; |
863 | if (time_before(jiffies + to, acb->scsi_host->last_reset - HZ / 2)) | 865 | if (time_before(jiffies + to, acb->last_reset - HZ / 2)) |
864 | acb->waiting_timer.expires = | 866 | acb->waiting_timer.expires = |
865 | acb->scsi_host->last_reset - HZ / 2 + 1; | 867 | acb->last_reset - HZ / 2 + 1; |
866 | else | 868 | else |
867 | acb->waiting_timer.expires = jiffies + to + 1; | 869 | acb->waiting_timer.expires = jiffies + to + 1; |
868 | add_timer(&acb->waiting_timer); | 870 | add_timer(&acb->waiting_timer); |
@@ -1319,7 +1321,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) | |||
1319 | udelay(500); | 1321 | udelay(500); |
1320 | 1322 | ||
1321 | /* We may be in serious trouble. Wait some seconds */ | 1323 | /* We may be in serious trouble. Wait some seconds */ |
1322 | acb->scsi_host->last_reset = | 1324 | acb->last_reset = |
1323 | jiffies + 3 * HZ / 2 + | 1325 | jiffies + 3 * HZ / 2 + |
1324 | HZ * acb->eeprom.delay_time; | 1326 | HZ * acb->eeprom.delay_time; |
1325 | 1327 | ||
@@ -1462,9 +1464,9 @@ static void selto_timer(struct AdapterCtlBlk *acb) | |||
1462 | acb->selto_timer.function = selection_timeout_missed; | 1464 | acb->selto_timer.function = selection_timeout_missed; |
1463 | acb->selto_timer.data = (unsigned long) acb; | 1465 | acb->selto_timer.data = (unsigned long) acb; |
1464 | if (time_before | 1466 | if (time_before |
1465 | (jiffies + HZ, acb->scsi_host->last_reset + HZ / 2)) | 1467 | (jiffies + HZ, acb->last_reset + HZ / 2)) |
1466 | acb->selto_timer.expires = | 1468 | acb->selto_timer.expires = |
1467 | acb->scsi_host->last_reset + HZ / 2 + 1; | 1469 | acb->last_reset + HZ / 2 + 1; |
1468 | else | 1470 | else |
1469 | acb->selto_timer.expires = jiffies + HZ + 1; | 1471 | acb->selto_timer.expires = jiffies + HZ + 1; |
1470 | add_timer(&acb->selto_timer); | 1472 | add_timer(&acb->selto_timer); |
@@ -1535,7 +1537,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, | |||
1535 | } | 1537 | } |
1536 | /* Allow starting of SCSI commands half a second before we allow the mid-level | 1538 | /* Allow starting of SCSI commands half a second before we allow the mid-level |
1537 | * to queue them again after a reset */ | 1539 | * to queue them again after a reset */ |
1538 | if (time_before(jiffies, acb->scsi_host->last_reset - HZ / 2)) { | 1540 | if (time_before(jiffies, acb->last_reset - HZ / 2)) { |
1539 | dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n"); | 1541 | dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n"); |
1540 | return 1; | 1542 | return 1; |
1541 | } | 1543 | } |
@@ -3031,7 +3033,7 @@ static void disconnect(struct AdapterCtlBlk *acb) | |||
3031 | dprintkl(KERN_ERR, "disconnect: No such device\n"); | 3033 | dprintkl(KERN_ERR, "disconnect: No such device\n"); |
3032 | udelay(500); | 3034 | udelay(500); |
3033 | /* Suspend queue for a while */ | 3035 | /* Suspend queue for a while */ |
3034 | acb->scsi_host->last_reset = | 3036 | acb->last_reset = |
3035 | jiffies + HZ / 2 + | 3037 | jiffies + HZ / 2 + |
3036 | HZ * acb->eeprom.delay_time; | 3038 | HZ * acb->eeprom.delay_time; |
3037 | clear_fifo(acb, "disconnectEx"); | 3039 | clear_fifo(acb, "disconnectEx"); |
@@ -3053,7 +3055,7 @@ static void disconnect(struct AdapterCtlBlk *acb) | |||
3053 | waiting_process_next(acb); | 3055 | waiting_process_next(acb); |
3054 | } else if (srb->state & SRB_ABORT_SENT) { | 3056 | } else if (srb->state & SRB_ABORT_SENT) { |
3055 | dcb->flag &= ~ABORT_DEV_; | 3057 | dcb->flag &= ~ABORT_DEV_; |
3056 | acb->scsi_host->last_reset = jiffies + HZ / 2 + 1; | 3058 | acb->last_reset = jiffies + HZ / 2 + 1; |
3057 | dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n"); | 3059 | dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n"); |
3058 | doing_srb_done(acb, DID_ABORT, srb->cmd, 1); | 3060 | doing_srb_done(acb, DID_ABORT, srb->cmd, 1); |
3059 | waiting_process_next(acb); | 3061 | waiting_process_next(acb); |
@@ -3649,7 +3651,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb) | |||
3649 | /*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */ | 3651 | /*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */ |
3650 | udelay(500); | 3652 | udelay(500); |
3651 | /* Maybe we locked up the bus? Then lets wait even longer ... */ | 3653 | /* Maybe we locked up the bus? Then lets wait even longer ... */ |
3652 | acb->scsi_host->last_reset = | 3654 | acb->last_reset = |
3653 | jiffies + 5 * HZ / 2 + | 3655 | jiffies + 5 * HZ / 2 + |
3654 | HZ * acb->eeprom.delay_time; | 3656 | HZ * acb->eeprom.delay_time; |
3655 | 3657 | ||
@@ -4426,7 +4428,7 @@ static void adapter_init_scsi_host(struct Scsi_Host *host) | |||
4426 | host->dma_channel = -1; | 4428 | host->dma_channel = -1; |
4427 | host->unique_id = acb->io_port_base; | 4429 | host->unique_id = acb->io_port_base; |
4428 | host->irq = acb->irq_level; | 4430 | host->irq = acb->irq_level; |
4429 | host->last_reset = jiffies; | 4431 | acb->last_reset = jiffies; |
4430 | 4432 | ||
4431 | host->max_id = 16; | 4433 | host->max_id = 16; |
4432 | if (host->max_id - 1 == eeprom->scsi_id) | 4434 | if (host->max_id - 1 == eeprom->scsi_id) |
@@ -4484,7 +4486,7 @@ static void adapter_init_chip(struct AdapterCtlBlk *acb) | |||
4484 | /*spin_unlock_irq (&io_request_lock); */ | 4486 | /*spin_unlock_irq (&io_request_lock); */ |
4485 | udelay(500); | 4487 | udelay(500); |
4486 | 4488 | ||
4487 | acb->scsi_host->last_reset = | 4489 | acb->last_reset = |
4488 | jiffies + HZ / 2 + | 4490 | jiffies + HZ / 2 + |
4489 | HZ * acb->eeprom.delay_time; | 4491 | HZ * acb->eeprom.delay_time; |
4490 | 4492 | ||
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 68adb8955d2d..5248c888552b 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -481,6 +481,11 @@ static int alua_check_sense(struct scsi_device *sdev, | |||
481 | * Power On, Reset, or Bus Device Reset, just retry. | 481 | * Power On, Reset, or Bus Device Reset, just retry. |
482 | */ | 482 | */ |
483 | return ADD_TO_MLQUEUE; | 483 | return ADD_TO_MLQUEUE; |
484 | if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x04) | ||
485 | /* | ||
486 | * Device internal reset | ||
487 | */ | ||
488 | return ADD_TO_MLQUEUE; | ||
484 | if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01) | 489 | if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01) |
485 | /* | 490 | /* |
486 | * Mode Parameters Changed | 491 | * Mode Parameters Changed |
@@ -517,12 +522,13 @@ static int alua_check_sense(struct scsi_device *sdev, | |||
517 | /* | 522 | /* |
518 | * alua_rtpg - Evaluate REPORT TARGET GROUP STATES | 523 | * alua_rtpg - Evaluate REPORT TARGET GROUP STATES |
519 | * @sdev: the device to be evaluated. | 524 | * @sdev: the device to be evaluated. |
525 | * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for device to exit transitioning state | ||
520 | * | 526 | * |
521 | * Evaluate the Target Port Group State. | 527 | * Evaluate the Target Port Group State. |
522 | * Returns SCSI_DH_DEV_OFFLINED if the path is | 528 | * Returns SCSI_DH_DEV_OFFLINED if the path is |
523 | * found to be unusable. | 529 | * found to be unusable. |
524 | */ | 530 | */ |
525 | static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | 531 | static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int wait_for_transition) |
526 | { | 532 | { |
527 | struct scsi_sense_hdr sense_hdr; | 533 | struct scsi_sense_hdr sense_hdr; |
528 | int len, k, off, valid_states = 0; | 534 | int len, k, off, valid_states = 0; |
@@ -594,7 +600,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | |||
594 | else | 600 | else |
595 | h->transition_tmo = ALUA_FAILOVER_TIMEOUT; | 601 | h->transition_tmo = ALUA_FAILOVER_TIMEOUT; |
596 | 602 | ||
597 | if (orig_transition_tmo != h->transition_tmo) { | 603 | if (wait_for_transition && (orig_transition_tmo != h->transition_tmo)) { |
598 | sdev_printk(KERN_INFO, sdev, | 604 | sdev_printk(KERN_INFO, sdev, |
599 | "%s: transition timeout set to %d seconds\n", | 605 | "%s: transition timeout set to %d seconds\n", |
600 | ALUA_DH_NAME, h->transition_tmo); | 606 | ALUA_DH_NAME, h->transition_tmo); |
@@ -632,14 +638,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) | |||
632 | 638 | ||
633 | switch (h->state) { | 639 | switch (h->state) { |
634 | case TPGS_STATE_TRANSITIONING: | 640 | case TPGS_STATE_TRANSITIONING: |
635 | if (time_before(jiffies, expiry)) { | 641 | if (wait_for_transition) { |
636 | /* State transition, retry */ | 642 | if (time_before(jiffies, expiry)) { |
637 | interval += 2000; | 643 | /* State transition, retry */ |
638 | msleep(interval); | 644 | interval += 2000; |
639 | goto retry; | 645 | msleep(interval); |
646 | goto retry; | ||
647 | } | ||
648 | err = SCSI_DH_RETRY; | ||
649 | } else { | ||
650 | err = SCSI_DH_OK; | ||
640 | } | 651 | } |
652 | |||
641 | /* Transitioning time exceeded, set port to standby */ | 653 | /* Transitioning time exceeded, set port to standby */ |
642 | err = SCSI_DH_RETRY; | ||
643 | h->state = TPGS_STATE_STANDBY; | 654 | h->state = TPGS_STATE_STANDBY; |
644 | break; | 655 | break; |
645 | case TPGS_STATE_OFFLINE: | 656 | case TPGS_STATE_OFFLINE: |
@@ -673,7 +684,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) | |||
673 | if (err != SCSI_DH_OK) | 684 | if (err != SCSI_DH_OK) |
674 | goto out; | 685 | goto out; |
675 | 686 | ||
676 | err = alua_rtpg(sdev, h); | 687 | err = alua_rtpg(sdev, h, 0); |
677 | if (err != SCSI_DH_OK) | 688 | if (err != SCSI_DH_OK) |
678 | goto out; | 689 | goto out; |
679 | 690 | ||
@@ -733,7 +744,7 @@ static int alua_activate(struct scsi_device *sdev, | |||
733 | int err = SCSI_DH_OK; | 744 | int err = SCSI_DH_OK; |
734 | int stpg = 0; | 745 | int stpg = 0; |
735 | 746 | ||
736 | err = alua_rtpg(sdev, h); | 747 | err = alua_rtpg(sdev, h, 1); |
737 | if (err != SCSI_DH_OK) | 748 | if (err != SCSI_DH_OK) |
738 | goto out; | 749 | goto out; |
739 | 750 | ||
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 69c915aa77c2..4b9cf93f3fb6 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -786,6 +786,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { | |||
786 | {"IBM", "1742"}, | 786 | {"IBM", "1742"}, |
787 | {"IBM", "1745"}, | 787 | {"IBM", "1745"}, |
788 | {"IBM", "1746"}, | 788 | {"IBM", "1746"}, |
789 | {"IBM", "1813"}, | ||
789 | {"IBM", "1814"}, | 790 | {"IBM", "1814"}, |
790 | {"IBM", "1815"}, | 791 | {"IBM", "1815"}, |
791 | {"IBM", "1818"}, | 792 | {"IBM", "1818"}, |
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 19e1b422260a..c0ae8fa57a3b 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
@@ -448,19 +448,8 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd | |||
448 | } | 448 | } |
449 | 449 | ||
450 | rmb(); | 450 | rmb(); |
451 | /* | 451 | if ((pHba->state) & DPTI_STATE_RESET) |
452 | * TODO: I need to block here if I am processing ioctl cmds | 452 | return SCSI_MLQUEUE_HOST_BUSY; |
453 | * but if the outstanding cmds all finish before the ioctl, | ||
454 | * the scsi-core will not know to start sending cmds to me again. | ||
455 | * I need to a way to restart the scsi-cores queues or should I block | ||
456 | * calling scsi_done on the outstanding cmds instead | ||
457 | * for now we don't set the IOCTL state | ||
458 | */ | ||
459 | if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) { | ||
460 | pHba->host->last_reset = jiffies; | ||
461 | pHba->host->resetting = 1; | ||
462 | return 1; | ||
463 | } | ||
464 | 453 | ||
465 | // TODO if the cmd->device if offline then I may need to issue a bus rescan | 454 | // TODO if the cmd->device if offline then I may need to issue a bus rescan |
466 | // followed by a get_lct to see if the device is there anymore | 455 | // followed by a get_lct to see if the device is there anymore |
@@ -1811,21 +1800,23 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) | |||
1811 | } | 1800 | } |
1812 | 1801 | ||
1813 | do { | 1802 | do { |
1814 | if(pHba->host) | 1803 | /* |
1804 | * Stop any new commands from enterring the | ||
1805 | * controller while processing the ioctl | ||
1806 | */ | ||
1807 | if (pHba->host) { | ||
1808 | scsi_block_requests(pHba->host); | ||
1815 | spin_lock_irqsave(pHba->host->host_lock, flags); | 1809 | spin_lock_irqsave(pHba->host->host_lock, flags); |
1816 | // This state stops any new commands from enterring the | 1810 | } |
1817 | // controller while processing the ioctl | ||
1818 | // pHba->state |= DPTI_STATE_IOCTL; | ||
1819 | // We can't set this now - The scsi subsystem sets host_blocked and | ||
1820 | // the queue empties and stops. We need a way to restart the queue | ||
1821 | rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); | 1811 | rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); |
1822 | if (rcode != 0) | 1812 | if (rcode != 0) |
1823 | printk("adpt_i2o_passthru: post wait failed %d %p\n", | 1813 | printk("adpt_i2o_passthru: post wait failed %d %p\n", |
1824 | rcode, reply); | 1814 | rcode, reply); |
1825 | // pHba->state &= ~DPTI_STATE_IOCTL; | 1815 | if (pHba->host) { |
1826 | if(pHba->host) | ||
1827 | spin_unlock_irqrestore(pHba->host->host_lock, flags); | 1816 | spin_unlock_irqrestore(pHba->host->host_lock, flags); |
1828 | } while(rcode == -ETIMEDOUT); | 1817 | scsi_unblock_requests(pHba->host); |
1818 | } | ||
1819 | } while (rcode == -ETIMEDOUT); | ||
1829 | 1820 | ||
1830 | if(rcode){ | 1821 | if(rcode){ |
1831 | goto cleanup; | 1822 | goto cleanup; |
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index beded716f93f..aeb046186c84 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h | |||
@@ -202,7 +202,6 @@ struct adpt_channel { | |||
202 | 202 | ||
203 | // HBA state flags | 203 | // HBA state flags |
204 | #define DPTI_STATE_RESET (0x01) | 204 | #define DPTI_STATE_RESET (0x01) |
205 | #define DPTI_STATE_IOCTL (0x02) | ||
206 | 205 | ||
207 | typedef struct _adpt_hba { | 206 | typedef struct _adpt_hba { |
208 | struct _adpt_hba *next; | 207 | struct _adpt_hba *next; |
diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index 0838e265e0b9..3fd305d6b67d 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h | |||
@@ -799,47 +799,47 @@ struct esas2r_adapter { | |||
799 | struct esas2r_target *targetdb_end; | 799 | struct esas2r_target *targetdb_end; |
800 | unsigned char *regs; | 800 | unsigned char *regs; |
801 | unsigned char *data_window; | 801 | unsigned char *data_window; |
802 | u32 volatile flags; | 802 | long flags; |
803 | #define AF_PORT_CHANGE (u32)(0x00000001) | 803 | #define AF_PORT_CHANGE 0 |
804 | #define AF_CHPRST_NEEDED (u32)(0x00000004) | 804 | #define AF_CHPRST_NEEDED 1 |
805 | #define AF_CHPRST_PENDING (u32)(0x00000008) | 805 | #define AF_CHPRST_PENDING 2 |
806 | #define AF_CHPRST_DETECTED (u32)(0x00000010) | 806 | #define AF_CHPRST_DETECTED 3 |
807 | #define AF_BUSRST_NEEDED (u32)(0x00000020) | 807 | #define AF_BUSRST_NEEDED 4 |
808 | #define AF_BUSRST_PENDING (u32)(0x00000040) | 808 | #define AF_BUSRST_PENDING 5 |
809 | #define AF_BUSRST_DETECTED (u32)(0x00000080) | 809 | #define AF_BUSRST_DETECTED 6 |
810 | #define AF_DISABLED (u32)(0x00000100) | 810 | #define AF_DISABLED 7 |
811 | #define AF_FLASH_LOCK (u32)(0x00000200) | 811 | #define AF_FLASH_LOCK 8 |
812 | #define AF_OS_RESET (u32)(0x00002000) | 812 | #define AF_OS_RESET 9 |
813 | #define AF_FLASHING (u32)(0x00004000) | 813 | #define AF_FLASHING 10 |
814 | #define AF_POWER_MGT (u32)(0x00008000) | 814 | #define AF_POWER_MGT 11 |
815 | #define AF_NVR_VALID (u32)(0x00010000) | 815 | #define AF_NVR_VALID 12 |
816 | #define AF_DEGRADED_MODE (u32)(0x00020000) | 816 | #define AF_DEGRADED_MODE 13 |
817 | #define AF_DISC_PENDING (u32)(0x00040000) | 817 | #define AF_DISC_PENDING 14 |
818 | #define AF_TASKLET_SCHEDULED (u32)(0x00080000) | 818 | #define AF_TASKLET_SCHEDULED 15 |
819 | #define AF_HEARTBEAT (u32)(0x00200000) | 819 | #define AF_HEARTBEAT 16 |
820 | #define AF_HEARTBEAT_ENB (u32)(0x00400000) | 820 | #define AF_HEARTBEAT_ENB 17 |
821 | #define AF_NOT_PRESENT (u32)(0x00800000) | 821 | #define AF_NOT_PRESENT 18 |
822 | #define AF_CHPRST_STARTED (u32)(0x01000000) | 822 | #define AF_CHPRST_STARTED 19 |
823 | #define AF_FIRST_INIT (u32)(0x02000000) | 823 | #define AF_FIRST_INIT 20 |
824 | #define AF_POWER_DOWN (u32)(0x04000000) | 824 | #define AF_POWER_DOWN 21 |
825 | #define AF_DISC_IN_PROG (u32)(0x08000000) | 825 | #define AF_DISC_IN_PROG 22 |
826 | #define AF_COMM_LIST_TOGGLE (u32)(0x10000000) | 826 | #define AF_COMM_LIST_TOGGLE 23 |
827 | #define AF_LEGACY_SGE_MODE (u32)(0x20000000) | 827 | #define AF_LEGACY_SGE_MODE 24 |
828 | #define AF_DISC_POLLED (u32)(0x40000000) | 828 | #define AF_DISC_POLLED 25 |
829 | u32 volatile flags2; | 829 | long flags2; |
830 | #define AF2_SERIAL_FLASH (u32)(0x00000001) | 830 | #define AF2_SERIAL_FLASH 0 |
831 | #define AF2_DEV_SCAN (u32)(0x00000002) | 831 | #define AF2_DEV_SCAN 1 |
832 | #define AF2_DEV_CNT_OK (u32)(0x00000004) | 832 | #define AF2_DEV_CNT_OK 2 |
833 | #define AF2_COREDUMP_AVAIL (u32)(0x00000008) | 833 | #define AF2_COREDUMP_AVAIL 3 |
834 | #define AF2_COREDUMP_SAVED (u32)(0x00000010) | 834 | #define AF2_COREDUMP_SAVED 4 |
835 | #define AF2_VDA_POWER_DOWN (u32)(0x00000100) | 835 | #define AF2_VDA_POWER_DOWN 5 |
836 | #define AF2_THUNDERLINK (u32)(0x00000200) | 836 | #define AF2_THUNDERLINK 6 |
837 | #define AF2_THUNDERBOLT (u32)(0x00000400) | 837 | #define AF2_THUNDERBOLT 7 |
838 | #define AF2_INIT_DONE (u32)(0x00000800) | 838 | #define AF2_INIT_DONE 8 |
839 | #define AF2_INT_PENDING (u32)(0x00001000) | 839 | #define AF2_INT_PENDING 9 |
840 | #define AF2_TIMER_TICK (u32)(0x00002000) | 840 | #define AF2_TIMER_TICK 10 |
841 | #define AF2_IRQ_CLAIMED (u32)(0x00004000) | 841 | #define AF2_IRQ_CLAIMED 11 |
842 | #define AF2_MSI_ENABLED (u32)(0x00008000) | 842 | #define AF2_MSI_ENABLED 12 |
843 | atomic_t disable_cnt; | 843 | atomic_t disable_cnt; |
844 | atomic_t dis_ints_cnt; | 844 | atomic_t dis_ints_cnt; |
845 | u32 int_stat; | 845 | u32 int_stat; |
@@ -1150,16 +1150,6 @@ void esas2r_queue_fw_event(struct esas2r_adapter *a, | |||
1150 | int data_sz); | 1150 | int data_sz); |
1151 | 1151 | ||
1152 | /* Inline functions */ | 1152 | /* Inline functions */ |
1153 | static inline u32 esas2r_lock_set_flags(volatile u32 *flags, u32 bits) | ||
1154 | { | ||
1155 | return test_and_set_bit(ilog2(bits), (volatile unsigned long *)flags); | ||
1156 | } | ||
1157 | |||
1158 | static inline u32 esas2r_lock_clear_flags(volatile u32 *flags, u32 bits) | ||
1159 | { | ||
1160 | return test_and_clear_bit(ilog2(bits), | ||
1161 | (volatile unsigned long *)flags); | ||
1162 | } | ||
1163 | 1153 | ||
1164 | /* Allocate a chip scatter/gather list entry */ | 1154 | /* Allocate a chip scatter/gather list entry */ |
1165 | static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a) | 1155 | static inline struct esas2r_mem_desc *esas2r_alloc_sgl(struct esas2r_adapter *a) |
@@ -1217,7 +1207,6 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq, | |||
1217 | struct esas2r_adapter *a) | 1207 | struct esas2r_adapter *a) |
1218 | { | 1208 | { |
1219 | union atto_vda_req *vrq = rq->vrq; | 1209 | union atto_vda_req *vrq = rq->vrq; |
1220 | u32 handle; | ||
1221 | 1210 | ||
1222 | INIT_LIST_HEAD(&rq->sg_table_head); | 1211 | INIT_LIST_HEAD(&rq->sg_table_head); |
1223 | rq->data_buf = (void *)(vrq + 1); | 1212 | rq->data_buf = (void *)(vrq + 1); |
@@ -1253,11 +1242,9 @@ static inline void esas2r_rq_init_request(struct esas2r_request *rq, | |||
1253 | 1242 | ||
1254 | /* | 1243 | /* |
1255 | * add a reference number to the handle to make it unique (until it | 1244 | * add a reference number to the handle to make it unique (until it |
1256 | * wraps of course) while preserving the upper word | 1245 | * wraps of course) while preserving the least significant word |
1257 | */ | 1246 | */ |
1258 | 1247 | vrq->scsi.handle = (a->cmd_ref_no++ << 16) | (u16)vrq->scsi.handle; | |
1259 | handle = be32_to_cpu(vrq->scsi.handle) & 0xFFFF0000; | ||
1260 | vrq->scsi.handle = cpu_to_be32(handle + a->cmd_ref_no++); | ||
1261 | 1248 | ||
1262 | /* | 1249 | /* |
1263 | * the following formats a SCSI request. the caller can override as | 1250 | * the following formats a SCSI request. the caller can override as |
@@ -1303,10 +1290,13 @@ static inline void esas2r_rq_destroy_request(struct esas2r_request *rq, | |||
1303 | 1290 | ||
1304 | static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a) | 1291 | static inline bool esas2r_is_tasklet_pending(struct esas2r_adapter *a) |
1305 | { | 1292 | { |
1306 | return (a->flags & (AF_BUSRST_NEEDED | AF_BUSRST_DETECTED | 1293 | |
1307 | | AF_CHPRST_NEEDED | AF_CHPRST_DETECTED | 1294 | return test_bit(AF_BUSRST_NEEDED, &a->flags) || |
1308 | | AF_PORT_CHANGE)) | 1295 | test_bit(AF_BUSRST_DETECTED, &a->flags) || |
1309 | ? true : false; | 1296 | test_bit(AF_CHPRST_NEEDED, &a->flags) || |
1297 | test_bit(AF_CHPRST_DETECTED, &a->flags) || | ||
1298 | test_bit(AF_PORT_CHANGE, &a->flags); | ||
1299 | |||
1310 | } | 1300 | } |
1311 | 1301 | ||
1312 | /* | 1302 | /* |
@@ -1345,24 +1335,24 @@ static inline void esas2r_enable_chip_interrupts(struct esas2r_adapter *a) | |||
1345 | static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a) | 1335 | static inline void esas2r_schedule_tasklet(struct esas2r_adapter *a) |
1346 | { | 1336 | { |
1347 | /* make sure we don't schedule twice */ | 1337 | /* make sure we don't schedule twice */ |
1348 | if (!(esas2r_lock_set_flags(&a->flags, AF_TASKLET_SCHEDULED) & | 1338 | if (!test_and_set_bit(AF_TASKLET_SCHEDULED, &a->flags)) |
1349 | ilog2(AF_TASKLET_SCHEDULED))) | ||
1350 | tasklet_hi_schedule(&a->tasklet); | 1339 | tasklet_hi_schedule(&a->tasklet); |
1351 | } | 1340 | } |
1352 | 1341 | ||
1353 | static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a) | 1342 | static inline void esas2r_enable_heartbeat(struct esas2r_adapter *a) |
1354 | { | 1343 | { |
1355 | if (!(a->flags & (AF_DEGRADED_MODE | AF_CHPRST_PENDING)) | 1344 | if (!test_bit(AF_DEGRADED_MODE, &a->flags) && |
1356 | && (a->nvram->options2 & SASNVR2_HEARTBEAT)) | 1345 | !test_bit(AF_CHPRST_PENDING, &a->flags) && |
1357 | esas2r_lock_set_flags(&a->flags, AF_HEARTBEAT_ENB); | 1346 | (a->nvram->options2 & SASNVR2_HEARTBEAT)) |
1347 | set_bit(AF_HEARTBEAT_ENB, &a->flags); | ||
1358 | else | 1348 | else |
1359 | esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB); | 1349 | clear_bit(AF_HEARTBEAT_ENB, &a->flags); |
1360 | } | 1350 | } |
1361 | 1351 | ||
1362 | static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a) | 1352 | static inline void esas2r_disable_heartbeat(struct esas2r_adapter *a) |
1363 | { | 1353 | { |
1364 | esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT_ENB); | 1354 | clear_bit(AF_HEARTBEAT_ENB, &a->flags); |
1365 | esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT); | 1355 | clear_bit(AF_HEARTBEAT, &a->flags); |
1366 | } | 1356 | } |
1367 | 1357 | ||
1368 | /* Set the initial state for resetting the adapter on the next pass through | 1358 | /* Set the initial state for resetting the adapter on the next pass through |
@@ -1372,9 +1362,9 @@ static inline void esas2r_local_reset_adapter(struct esas2r_adapter *a) | |||
1372 | { | 1362 | { |
1373 | esas2r_disable_heartbeat(a); | 1363 | esas2r_disable_heartbeat(a); |
1374 | 1364 | ||
1375 | esas2r_lock_set_flags(&a->flags, AF_CHPRST_NEEDED); | 1365 | set_bit(AF_CHPRST_NEEDED, &a->flags); |
1376 | esas2r_lock_set_flags(&a->flags, AF_CHPRST_PENDING); | 1366 | set_bit(AF_CHPRST_PENDING, &a->flags); |
1377 | esas2r_lock_set_flags(&a->flags, AF_DISC_PENDING); | 1367 | set_bit(AF_DISC_PENDING, &a->flags); |
1378 | } | 1368 | } |
1379 | 1369 | ||
1380 | /* See if an interrupt is pending on the adapter. */ | 1370 | /* See if an interrupt is pending on the adapter. */ |
diff --git a/drivers/scsi/esas2r/esas2r_disc.c b/drivers/scsi/esas2r/esas2r_disc.c index dec6c334ce3e..1c079f4300a5 100644 --- a/drivers/scsi/esas2r/esas2r_disc.c +++ b/drivers/scsi/esas2r/esas2r_disc.c | |||
@@ -86,9 +86,9 @@ void esas2r_disc_initialize(struct esas2r_adapter *a) | |||
86 | 86 | ||
87 | esas2r_trace_enter(); | 87 | esas2r_trace_enter(); |
88 | 88 | ||
89 | esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); | 89 | clear_bit(AF_DISC_IN_PROG, &a->flags); |
90 | esas2r_lock_clear_flags(&a->flags2, AF2_DEV_SCAN); | 90 | clear_bit(AF2_DEV_SCAN, &a->flags2); |
91 | esas2r_lock_clear_flags(&a->flags2, AF2_DEV_CNT_OK); | 91 | clear_bit(AF2_DEV_CNT_OK, &a->flags2); |
92 | 92 | ||
93 | a->disc_start_time = jiffies_to_msecs(jiffies); | 93 | a->disc_start_time = jiffies_to_msecs(jiffies); |
94 | a->disc_wait_time = nvr->dev_wait_time * 1000; | 94 | a->disc_wait_time = nvr->dev_wait_time * 1000; |
@@ -107,7 +107,8 @@ void esas2r_disc_initialize(struct esas2r_adapter *a) | |||
107 | 107 | ||
108 | a->general_req.interrupt_cx = NULL; | 108 | a->general_req.interrupt_cx = NULL; |
109 | 109 | ||
110 | if (a->flags & (AF_CHPRST_DETECTED | AF_POWER_MGT)) { | 110 | if (test_bit(AF_CHPRST_DETECTED, &a->flags) || |
111 | test_bit(AF_POWER_MGT, &a->flags)) { | ||
111 | if (a->prev_dev_cnt == 0) { | 112 | if (a->prev_dev_cnt == 0) { |
112 | /* Don't bother waiting if there is nothing to wait | 113 | /* Don't bother waiting if there is nothing to wait |
113 | * for. | 114 | * for. |
@@ -212,9 +213,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) | |||
212 | || a->disc_wait_cnt == 0)) { | 213 | || a->disc_wait_cnt == 0)) { |
213 | /* After three seconds of waiting, schedule a scan. */ | 214 | /* After three seconds of waiting, schedule a scan. */ |
214 | if (time >= 3000 | 215 | if (time >= 3000 |
215 | && !(esas2r_lock_set_flags(&a->flags2, | 216 | && !test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) { |
216 | AF2_DEV_SCAN) & | ||
217 | ilog2(AF2_DEV_SCAN))) { | ||
218 | spin_lock_irqsave(&a->mem_lock, flags); | 217 | spin_lock_irqsave(&a->mem_lock, flags); |
219 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); | 218 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); |
220 | spin_unlock_irqrestore(&a->mem_lock, flags); | 219 | spin_unlock_irqrestore(&a->mem_lock, flags); |
@@ -228,18 +227,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) | |||
228 | * We are done waiting...we think. Adjust the wait time to | 227 | * We are done waiting...we think. Adjust the wait time to |
229 | * consume events after the count is met. | 228 | * consume events after the count is met. |
230 | */ | 229 | */ |
231 | if (!(esas2r_lock_set_flags(&a->flags2, AF2_DEV_CNT_OK) | 230 | if (!test_and_set_bit(AF2_DEV_CNT_OK, &a->flags2)) |
232 | & ilog2(AF2_DEV_CNT_OK))) | ||
233 | a->disc_wait_time = time + 3000; | 231 | a->disc_wait_time = time + 3000; |
234 | 232 | ||
235 | /* If we haven't done a full scan yet, do it now. */ | 233 | /* If we haven't done a full scan yet, do it now. */ |
236 | if (!(esas2r_lock_set_flags(&a->flags2, | 234 | if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) { |
237 | AF2_DEV_SCAN) & | ||
238 | ilog2(AF2_DEV_SCAN))) { | ||
239 | spin_lock_irqsave(&a->mem_lock, flags); | 235 | spin_lock_irqsave(&a->mem_lock, flags); |
240 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); | 236 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); |
241 | spin_unlock_irqrestore(&a->mem_lock, flags); | 237 | spin_unlock_irqrestore(&a->mem_lock, flags); |
242 | |||
243 | esas2r_trace_exit(); | 238 | esas2r_trace_exit(); |
244 | return; | 239 | return; |
245 | } | 240 | } |
@@ -253,9 +248,7 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) | |||
253 | return; | 248 | return; |
254 | } | 249 | } |
255 | } else { | 250 | } else { |
256 | if (!(esas2r_lock_set_flags(&a->flags2, | 251 | if (!test_and_set_bit(AF2_DEV_SCAN, &a->flags2)) { |
257 | AF2_DEV_SCAN) & | ||
258 | ilog2(AF2_DEV_SCAN))) { | ||
259 | spin_lock_irqsave(&a->mem_lock, flags); | 252 | spin_lock_irqsave(&a->mem_lock, flags); |
260 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); | 253 | esas2r_disc_queue_event(a, DCDE_DEV_SCAN); |
261 | spin_unlock_irqrestore(&a->mem_lock, flags); | 254 | spin_unlock_irqrestore(&a->mem_lock, flags); |
@@ -265,8 +258,8 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) | |||
265 | /* We want to stop waiting for devices. */ | 258 | /* We want to stop waiting for devices. */ |
266 | a->disc_wait_time = 0; | 259 | a->disc_wait_time = 0; |
267 | 260 | ||
268 | if ((a->flags & AF_DISC_POLLED) | 261 | if (test_bit(AF_DISC_POLLED, &a->flags) && |
269 | && (a->flags & AF_DISC_IN_PROG)) { | 262 | test_bit(AF_DISC_IN_PROG, &a->flags)) { |
270 | /* | 263 | /* |
271 | * Polled discovery is still pending so continue the active | 264 | * Polled discovery is still pending so continue the active |
272 | * discovery until it is done. At that point, we will stop | 265 | * discovery until it is done. At that point, we will stop |
@@ -280,14 +273,14 @@ void esas2r_disc_check_complete(struct esas2r_adapter *a) | |||
280 | * driven; i.e. There is no transition. | 273 | * driven; i.e. There is no transition. |
281 | */ | 274 | */ |
282 | esas2r_disc_fix_curr_requests(a); | 275 | esas2r_disc_fix_curr_requests(a); |
283 | esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); | 276 | clear_bit(AF_DISC_PENDING, &a->flags); |
284 | 277 | ||
285 | /* | 278 | /* |
286 | * We have deferred target state changes until now because we | 279 | * We have deferred target state changes until now because we |
287 | * don't want to report any removals (due to the first arrival) | 280 | * don't want to report any removals (due to the first arrival) |
288 | * until the device wait time expires. | 281 | * until the device wait time expires. |
289 | */ | 282 | */ |
290 | esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE); | 283 | set_bit(AF_PORT_CHANGE, &a->flags); |
291 | } | 284 | } |
292 | 285 | ||
293 | esas2r_trace_exit(); | 286 | esas2r_trace_exit(); |
@@ -308,7 +301,8 @@ void esas2r_disc_queue_event(struct esas2r_adapter *a, u8 disc_evt) | |||
308 | * Don't start discovery before or during polled discovery. if we did, | 301 | * Don't start discovery before or during polled discovery. if we did, |
309 | * we would have a deadlock if we are in the ISR already. | 302 | * we would have a deadlock if we are in the ISR already. |
310 | */ | 303 | */ |
311 | if (!(a->flags & (AF_CHPRST_PENDING | AF_DISC_POLLED))) | 304 | if (!test_bit(AF_CHPRST_PENDING, &a->flags) && |
305 | !test_bit(AF_DISC_POLLED, &a->flags)) | ||
312 | esas2r_disc_start_port(a); | 306 | esas2r_disc_start_port(a); |
313 | 307 | ||
314 | esas2r_trace_exit(); | 308 | esas2r_trace_exit(); |
@@ -322,7 +316,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) | |||
322 | 316 | ||
323 | esas2r_trace_enter(); | 317 | esas2r_trace_enter(); |
324 | 318 | ||
325 | if (a->flags & AF_DISC_IN_PROG) { | 319 | if (test_bit(AF_DISC_IN_PROG, &a->flags)) { |
326 | esas2r_trace_exit(); | 320 | esas2r_trace_exit(); |
327 | 321 | ||
328 | return false; | 322 | return false; |
@@ -330,7 +324,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) | |||
330 | 324 | ||
331 | /* If there is a discovery waiting, process it. */ | 325 | /* If there is a discovery waiting, process it. */ |
332 | if (dc->disc_evt) { | 326 | if (dc->disc_evt) { |
333 | if ((a->flags & AF_DISC_POLLED) | 327 | if (test_bit(AF_DISC_POLLED, &a->flags) |
334 | && a->disc_wait_time == 0) { | 328 | && a->disc_wait_time == 0) { |
335 | /* | 329 | /* |
336 | * We are doing polled discovery, but we no longer want | 330 | * We are doing polled discovery, but we no longer want |
@@ -347,7 +341,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) | |||
347 | 341 | ||
348 | esas2r_hdebug("disc done"); | 342 | esas2r_hdebug("disc done"); |
349 | 343 | ||
350 | esas2r_lock_set_flags(&a->flags, AF_PORT_CHANGE); | 344 | set_bit(AF_PORT_CHANGE, &a->flags); |
351 | 345 | ||
352 | esas2r_trace_exit(); | 346 | esas2r_trace_exit(); |
353 | 347 | ||
@@ -356,10 +350,10 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) | |||
356 | 350 | ||
357 | /* Handle the discovery context */ | 351 | /* Handle the discovery context */ |
358 | esas2r_trace("disc_evt: %d", dc->disc_evt); | 352 | esas2r_trace("disc_evt: %d", dc->disc_evt); |
359 | esas2r_lock_set_flags(&a->flags, AF_DISC_IN_PROG); | 353 | set_bit(AF_DISC_IN_PROG, &a->flags); |
360 | dc->flags = 0; | 354 | dc->flags = 0; |
361 | 355 | ||
362 | if (a->flags & AF_DISC_POLLED) | 356 | if (test_bit(AF_DISC_POLLED, &a->flags)) |
363 | dc->flags |= DCF_POLLED; | 357 | dc->flags |= DCF_POLLED; |
364 | 358 | ||
365 | rq->interrupt_cx = dc; | 359 | rq->interrupt_cx = dc; |
@@ -379,7 +373,7 @@ bool esas2r_disc_start_port(struct esas2r_adapter *a) | |||
379 | } | 373 | } |
380 | 374 | ||
381 | /* Continue interrupt driven discovery */ | 375 | /* Continue interrupt driven discovery */ |
382 | if (!(a->flags & AF_DISC_POLLED)) | 376 | if (!test_bit(AF_DISC_POLLED, &a->flags)) |
383 | ret = esas2r_disc_continue(a, rq); | 377 | ret = esas2r_disc_continue(a, rq); |
384 | else | 378 | else |
385 | ret = true; | 379 | ret = true; |
@@ -453,10 +447,10 @@ static bool esas2r_disc_continue(struct esas2r_adapter *a, | |||
453 | /* Discovery is done...for now. */ | 447 | /* Discovery is done...for now. */ |
454 | rq->interrupt_cx = NULL; | 448 | rq->interrupt_cx = NULL; |
455 | 449 | ||
456 | if (!(a->flags & AF_DISC_PENDING)) | 450 | if (!test_bit(AF_DISC_PENDING, &a->flags)) |
457 | esas2r_disc_fix_curr_requests(a); | 451 | esas2r_disc_fix_curr_requests(a); |
458 | 452 | ||
459 | esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); | 453 | clear_bit(AF_DISC_IN_PROG, &a->flags); |
460 | 454 | ||
461 | /* Start the next discovery. */ | 455 | /* Start the next discovery. */ |
462 | return esas2r_disc_start_port(a); | 456 | return esas2r_disc_start_port(a); |
@@ -480,7 +474,8 @@ static bool esas2r_disc_start_request(struct esas2r_adapter *a, | |||
480 | 474 | ||
481 | spin_lock_irqsave(&a->queue_lock, flags); | 475 | spin_lock_irqsave(&a->queue_lock, flags); |
482 | 476 | ||
483 | if (!(a->flags & (AF_CHPRST_PENDING | AF_FLASHING))) | 477 | if (!test_bit(AF_CHPRST_PENDING, &a->flags) && |
478 | !test_bit(AF_FLASHING, &a->flags)) | ||
484 | esas2r_disc_local_start_request(a, rq); | 479 | esas2r_disc_local_start_request(a, rq); |
485 | else | 480 | else |
486 | list_add_tail(&rq->req_list, &a->defer_list); | 481 | list_add_tail(&rq->req_list, &a->defer_list); |
diff --git a/drivers/scsi/esas2r/esas2r_flash.c b/drivers/scsi/esas2r/esas2r_flash.c index 2ec3c23275b8..b7dc59fca7a6 100644 --- a/drivers/scsi/esas2r/esas2r_flash.c +++ b/drivers/scsi/esas2r/esas2r_flash.c | |||
@@ -231,7 +231,7 @@ static bool load_image(struct esas2r_adapter *a, struct esas2r_request *rq) | |||
231 | * RS_PENDING, FM API tasks will continue. | 231 | * RS_PENDING, FM API tasks will continue. |
232 | */ | 232 | */ |
233 | rq->req_stat = RS_PENDING; | 233 | rq->req_stat = RS_PENDING; |
234 | if (a->flags & AF_DEGRADED_MODE) | 234 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
235 | /* not suppported for now */; | 235 | /* not suppported for now */; |
236 | else | 236 | else |
237 | build_flash_msg(a, rq); | 237 | build_flash_msg(a, rq); |
@@ -315,7 +315,7 @@ static bool complete_fmapi_req(struct esas2r_adapter *a, | |||
315 | memset(fc->scratch, 0, FM_BUF_SZ); | 315 | memset(fc->scratch, 0, FM_BUF_SZ); |
316 | 316 | ||
317 | esas2r_enable_heartbeat(a); | 317 | esas2r_enable_heartbeat(a); |
318 | esas2r_lock_clear_flags(&a->flags, AF_FLASH_LOCK); | 318 | clear_bit(AF_FLASH_LOCK, &a->flags); |
319 | return false; | 319 | return false; |
320 | } | 320 | } |
321 | 321 | ||
@@ -526,7 +526,7 @@ no_cfg: | |||
526 | * The download is complete. If in degraded mode, | 526 | * The download is complete. If in degraded mode, |
527 | * attempt a chip reset. | 527 | * attempt a chip reset. |
528 | */ | 528 | */ |
529 | if (a->flags & AF_DEGRADED_MODE) | 529 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
530 | esas2r_local_reset_adapter(a); | 530 | esas2r_local_reset_adapter(a); |
531 | 531 | ||
532 | a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version; | 532 | a->flash_ver = fi->cmp_hdr[CH_IT_BIOS].version; |
@@ -890,7 +890,7 @@ bool esas2r_process_fs_ioctl(struct esas2r_adapter *a, | |||
890 | } | 890 | } |
891 | } | 891 | } |
892 | 892 | ||
893 | if (a->flags & AF_DEGRADED_MODE) { | 893 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) { |
894 | fs->status = ATTO_STS_DEGRADED; | 894 | fs->status = ATTO_STS_DEGRADED; |
895 | return false; | 895 | return false; |
896 | } | 896 | } |
@@ -945,8 +945,12 @@ static bool esas2r_flash_access(struct esas2r_adapter *a, u32 function) | |||
945 | 945 | ||
946 | /* Now wait for the firmware to process it */ | 946 | /* Now wait for the firmware to process it */ |
947 | starttime = jiffies_to_msecs(jiffies); | 947 | starttime = jiffies_to_msecs(jiffies); |
948 | timeout = a->flags & | 948 | |
949 | (AF_CHPRST_PENDING | AF_DISC_PENDING) ? 40000 : 5000; | 949 | if (test_bit(AF_CHPRST_PENDING, &a->flags) || |
950 | test_bit(AF_DISC_PENDING, &a->flags)) | ||
951 | timeout = 40000; | ||
952 | else | ||
953 | timeout = 5000; | ||
950 | 954 | ||
951 | while (true) { | 955 | while (true) { |
952 | intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT); | 956 | intstat = esas2r_read_register_dword(a, MU_INT_STATUS_OUT); |
@@ -1008,7 +1012,7 @@ bool esas2r_read_flash_block(struct esas2r_adapter *a, | |||
1008 | u32 offset; | 1012 | u32 offset; |
1009 | u32 iatvr; | 1013 | u32 iatvr; |
1010 | 1014 | ||
1011 | if (a->flags2 & AF2_SERIAL_FLASH) | 1015 | if (test_bit(AF2_SERIAL_FLASH, &a->flags2)) |
1012 | iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE); | 1016 | iatvr = MW_DATA_ADDR_SER_FLASH + (from & -WINDOW_SIZE); |
1013 | else | 1017 | else |
1014 | iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE); | 1018 | iatvr = MW_DATA_ADDR_PAR_FLASH + (from & -WINDOW_SIZE); |
@@ -1236,9 +1240,9 @@ static void esas2r_nvram_callback(struct esas2r_adapter *a, | |||
1236 | if (rq->req_stat != RS_PENDING) { | 1240 | if (rq->req_stat != RS_PENDING) { |
1237 | /* update the NVRAM state */ | 1241 | /* update the NVRAM state */ |
1238 | if (rq->req_stat == RS_SUCCESS) | 1242 | if (rq->req_stat == RS_SUCCESS) |
1239 | esas2r_lock_set_flags(&a->flags, AF_NVR_VALID); | 1243 | set_bit(AF_NVR_VALID, &a->flags); |
1240 | else | 1244 | else |
1241 | esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID); | 1245 | clear_bit(AF_NVR_VALID, &a->flags); |
1242 | 1246 | ||
1243 | esas2r_enable_heartbeat(a); | 1247 | esas2r_enable_heartbeat(a); |
1244 | 1248 | ||
@@ -1258,7 +1262,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, | |||
1258 | u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0]; | 1262 | u32 *sas_address_dwords = (u32 *)&sas_address_bytes[0]; |
1259 | struct atto_vda_flash_req *vrq = &rq->vrq->flash; | 1263 | struct atto_vda_flash_req *vrq = &rq->vrq->flash; |
1260 | 1264 | ||
1261 | if (a->flags & AF_DEGRADED_MODE) | 1265 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1262 | return false; | 1266 | return false; |
1263 | 1267 | ||
1264 | if (down_interruptible(&a->nvram_semaphore)) | 1268 | if (down_interruptible(&a->nvram_semaphore)) |
@@ -1302,7 +1306,7 @@ bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, | |||
1302 | FLS_OFFSET_NVR, | 1306 | FLS_OFFSET_NVR, |
1303 | sizeof(struct esas2r_sas_nvram)); | 1307 | sizeof(struct esas2r_sas_nvram)); |
1304 | 1308 | ||
1305 | if (a->flags & AF_LEGACY_SGE_MODE) { | 1309 | if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) { |
1306 | 1310 | ||
1307 | vrq->data.sge[0].length = | 1311 | vrq->data.sge[0].length = |
1308 | cpu_to_le32(SGE_LAST | | 1312 | cpu_to_le32(SGE_LAST | |
@@ -1337,7 +1341,7 @@ bool esas2r_nvram_validate(struct esas2r_adapter *a) | |||
1337 | } else if (n->version > SASNVR_VERSION) { | 1341 | } else if (n->version > SASNVR_VERSION) { |
1338 | esas2r_hdebug("invalid NVRAM version"); | 1342 | esas2r_hdebug("invalid NVRAM version"); |
1339 | } else { | 1343 | } else { |
1340 | esas2r_lock_set_flags(&a->flags, AF_NVR_VALID); | 1344 | set_bit(AF_NVR_VALID, &a->flags); |
1341 | rslt = true; | 1345 | rslt = true; |
1342 | } | 1346 | } |
1343 | 1347 | ||
@@ -1359,7 +1363,7 @@ void esas2r_nvram_set_defaults(struct esas2r_adapter *a) | |||
1359 | struct esas2r_sas_nvram *n = a->nvram; | 1363 | struct esas2r_sas_nvram *n = a->nvram; |
1360 | u32 time = jiffies_to_msecs(jiffies); | 1364 | u32 time = jiffies_to_msecs(jiffies); |
1361 | 1365 | ||
1362 | esas2r_lock_clear_flags(&a->flags, AF_NVR_VALID); | 1366 | clear_bit(AF_NVR_VALID, &a->flags); |
1363 | *n = default_sas_nvram; | 1367 | *n = default_sas_nvram; |
1364 | n->sas_addr[3] |= 0x0F; | 1368 | n->sas_addr[3] |= 0x0F; |
1365 | n->sas_addr[4] = HIBYTE(LOWORD(time)); | 1369 | n->sas_addr[4] = HIBYTE(LOWORD(time)); |
@@ -1389,7 +1393,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, | |||
1389 | u8 j; | 1393 | u8 j; |
1390 | struct esas2r_component_header *ch; | 1394 | struct esas2r_component_header *ch; |
1391 | 1395 | ||
1392 | if (esas2r_lock_set_flags(&a->flags, AF_FLASH_LOCK) & AF_FLASH_LOCK) { | 1396 | if (test_and_set_bit(AF_FLASH_LOCK, &a->flags)) { |
1393 | /* flag was already set */ | 1397 | /* flag was already set */ |
1394 | fi->status = FI_STAT_BUSY; | 1398 | fi->status = FI_STAT_BUSY; |
1395 | return false; | 1399 | return false; |
@@ -1413,7 +1417,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, | |||
1413 | return complete_fmapi_req(a, rq, FI_STAT_IMG_VER); | 1417 | return complete_fmapi_req(a, rq, FI_STAT_IMG_VER); |
1414 | } | 1418 | } |
1415 | 1419 | ||
1416 | if (a->flags & AF_DEGRADED_MODE) | 1420 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1417 | return complete_fmapi_req(a, rq, FI_STAT_DEGRADED); | 1421 | return complete_fmapi_req(a, rq, FI_STAT_DEGRADED); |
1418 | 1422 | ||
1419 | switch (fi->action) { | 1423 | switch (fi->action) { |
diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index da1869df2408..b9750e296d71 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c | |||
@@ -216,7 +216,7 @@ use_legacy_interrupts: | |||
216 | goto use_legacy_interrupts; | 216 | goto use_legacy_interrupts; |
217 | } | 217 | } |
218 | a->intr_mode = INTR_MODE_MSI; | 218 | a->intr_mode = INTR_MODE_MSI; |
219 | esas2r_lock_set_flags(&a->flags2, AF2_MSI_ENABLED); | 219 | set_bit(AF2_MSI_ENABLED, &a->flags2); |
220 | break; | 220 | break; |
221 | 221 | ||
222 | 222 | ||
@@ -252,7 +252,7 @@ static void esas2r_claim_interrupts(struct esas2r_adapter *a) | |||
252 | return; | 252 | return; |
253 | } | 253 | } |
254 | 254 | ||
255 | esas2r_lock_set_flags(&a->flags2, AF2_IRQ_CLAIMED); | 255 | set_bit(AF2_IRQ_CLAIMED, &a->flags2); |
256 | esas2r_log(ESAS2R_LOG_INFO, | 256 | esas2r_log(ESAS2R_LOG_INFO, |
257 | "claimed IRQ %d flags: 0x%lx", | 257 | "claimed IRQ %d flags: 0x%lx", |
258 | a->pcid->irq, flags); | 258 | a->pcid->irq, flags); |
@@ -380,10 +380,10 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, | |||
380 | /* interrupts will be disabled until we are done with init */ | 380 | /* interrupts will be disabled until we are done with init */ |
381 | atomic_inc(&a->dis_ints_cnt); | 381 | atomic_inc(&a->dis_ints_cnt); |
382 | atomic_inc(&a->disable_cnt); | 382 | atomic_inc(&a->disable_cnt); |
383 | a->flags |= AF_CHPRST_PENDING | 383 | set_bit(AF_CHPRST_PENDING, &a->flags); |
384 | | AF_DISC_PENDING | 384 | set_bit(AF_DISC_PENDING, &a->flags); |
385 | | AF_FIRST_INIT | 385 | set_bit(AF_FIRST_INIT, &a->flags); |
386 | | AF_LEGACY_SGE_MODE; | 386 | set_bit(AF_LEGACY_SGE_MODE, &a->flags); |
387 | 387 | ||
388 | a->init_msg = ESAS2R_INIT_MSG_START; | 388 | a->init_msg = ESAS2R_INIT_MSG_START; |
389 | a->max_vdareq_size = 128; | 389 | a->max_vdareq_size = 128; |
@@ -440,11 +440,11 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, | |||
440 | 440 | ||
441 | esas2r_claim_interrupts(a); | 441 | esas2r_claim_interrupts(a); |
442 | 442 | ||
443 | if (a->flags2 & AF2_IRQ_CLAIMED) | 443 | if (test_bit(AF2_IRQ_CLAIMED, &a->flags2)) |
444 | esas2r_enable_chip_interrupts(a); | 444 | esas2r_enable_chip_interrupts(a); |
445 | 445 | ||
446 | esas2r_lock_set_flags(&a->flags2, AF2_INIT_DONE); | 446 | set_bit(AF2_INIT_DONE, &a->flags2); |
447 | if (!(a->flags & AF_DEGRADED_MODE)) | 447 | if (!test_bit(AF_DEGRADED_MODE, &a->flags)) |
448 | esas2r_kickoff_timer(a); | 448 | esas2r_kickoff_timer(a); |
449 | esas2r_debug("esas2r_init_adapter done for %p (%d)", | 449 | esas2r_debug("esas2r_init_adapter done for %p (%d)", |
450 | a, a->disable_cnt); | 450 | a, a->disable_cnt); |
@@ -457,8 +457,8 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a, | |||
457 | { | 457 | { |
458 | struct esas2r_mem_desc *memdesc, *next; | 458 | struct esas2r_mem_desc *memdesc, *next; |
459 | 459 | ||
460 | if ((a->flags2 & AF2_INIT_DONE) | 460 | if ((test_bit(AF2_INIT_DONE, &a->flags2)) |
461 | && (!(a->flags & AF_DEGRADED_MODE))) { | 461 | && (!test_bit(AF_DEGRADED_MODE, &a->flags))) { |
462 | if (!power_management) { | 462 | if (!power_management) { |
463 | del_timer_sync(&a->timer); | 463 | del_timer_sync(&a->timer); |
464 | tasklet_kill(&a->tasklet); | 464 | tasklet_kill(&a->tasklet); |
@@ -508,19 +508,19 @@ static void esas2r_adapter_power_down(struct esas2r_adapter *a, | |||
508 | } | 508 | } |
509 | 509 | ||
510 | /* Clean up interrupts */ | 510 | /* Clean up interrupts */ |
511 | if (a->flags2 & AF2_IRQ_CLAIMED) { | 511 | if (test_bit(AF2_IRQ_CLAIMED, &a->flags2)) { |
512 | esas2r_log_dev(ESAS2R_LOG_INFO, | 512 | esas2r_log_dev(ESAS2R_LOG_INFO, |
513 | &(a->pcid->dev), | 513 | &(a->pcid->dev), |
514 | "free_irq(%d) called", a->pcid->irq); | 514 | "free_irq(%d) called", a->pcid->irq); |
515 | 515 | ||
516 | free_irq(a->pcid->irq, a); | 516 | free_irq(a->pcid->irq, a); |
517 | esas2r_debug("IRQ released"); | 517 | esas2r_debug("IRQ released"); |
518 | esas2r_lock_clear_flags(&a->flags2, AF2_IRQ_CLAIMED); | 518 | clear_bit(AF2_IRQ_CLAIMED, &a->flags2); |
519 | } | 519 | } |
520 | 520 | ||
521 | if (a->flags2 & AF2_MSI_ENABLED) { | 521 | if (test_bit(AF2_MSI_ENABLED, &a->flags2)) { |
522 | pci_disable_msi(a->pcid); | 522 | pci_disable_msi(a->pcid); |
523 | esas2r_lock_clear_flags(&a->flags2, AF2_MSI_ENABLED); | 523 | clear_bit(AF2_MSI_ENABLED, &a->flags2); |
524 | esas2r_debug("MSI disabled"); | 524 | esas2r_debug("MSI disabled"); |
525 | } | 525 | } |
526 | 526 | ||
@@ -641,12 +641,10 @@ void esas2r_kill_adapter(int i) | |||
641 | pci_set_drvdata(a->pcid, NULL); | 641 | pci_set_drvdata(a->pcid, NULL); |
642 | esas2r_adapters[i] = NULL; | 642 | esas2r_adapters[i] = NULL; |
643 | 643 | ||
644 | if (a->flags2 & AF2_INIT_DONE) { | 644 | if (test_bit(AF2_INIT_DONE, &a->flags2)) { |
645 | esas2r_lock_clear_flags(&a->flags2, | 645 | clear_bit(AF2_INIT_DONE, &a->flags2); |
646 | AF2_INIT_DONE); | ||
647 | 646 | ||
648 | esas2r_lock_set_flags(&a->flags, | 647 | set_bit(AF_DEGRADED_MODE, &a->flags); |
649 | AF_DEGRADED_MODE); | ||
650 | 648 | ||
651 | esas2r_log_dev(ESAS2R_LOG_INFO, | 649 | esas2r_log_dev(ESAS2R_LOG_INFO, |
652 | &(a->host->shost_gendev), | 650 | &(a->host->shost_gendev), |
@@ -759,7 +757,7 @@ int esas2r_resume(struct pci_dev *pdev) | |||
759 | 757 | ||
760 | esas2r_claim_interrupts(a); | 758 | esas2r_claim_interrupts(a); |
761 | 759 | ||
762 | if (a->flags2 & AF2_IRQ_CLAIMED) { | 760 | if (test_bit(AF2_IRQ_CLAIMED, &a->flags2)) { |
763 | /* | 761 | /* |
764 | * Now that system interrupt(s) are claimed, we can enable | 762 | * Now that system interrupt(s) are claimed, we can enable |
765 | * chip interrupts. | 763 | * chip interrupts. |
@@ -781,7 +779,7 @@ error_exit: | |||
781 | 779 | ||
782 | bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str) | 780 | bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str) |
783 | { | 781 | { |
784 | esas2r_lock_set_flags(&a->flags, AF_DEGRADED_MODE); | 782 | set_bit(AF_DEGRADED_MODE, &a->flags); |
785 | esas2r_log(ESAS2R_LOG_CRIT, | 783 | esas2r_log(ESAS2R_LOG_CRIT, |
786 | "setting adapter to degraded mode: %s\n", error_str); | 784 | "setting adapter to degraded mode: %s\n", error_str); |
787 | return false; | 785 | return false; |
@@ -809,7 +807,7 @@ static void esas2r_init_pci_cfg_space(struct esas2r_adapter *a) | |||
809 | int pcie_cap_reg; | 807 | int pcie_cap_reg; |
810 | 808 | ||
811 | pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP); | 809 | pcie_cap_reg = pci_find_capability(a->pcid, PCI_CAP_ID_EXP); |
812 | if (0xffff & pcie_cap_reg) { | 810 | if (pcie_cap_reg) { |
813 | u16 devcontrol; | 811 | u16 devcontrol; |
814 | 812 | ||
815 | pci_read_config_word(a->pcid, pcie_cap_reg + PCI_EXP_DEVCTL, | 813 | pci_read_config_word(a->pcid, pcie_cap_reg + PCI_EXP_DEVCTL, |
@@ -896,7 +894,7 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, | |||
896 | && (a->pcid->subsystem_device & ATTO_SSDID_TBT)) | 894 | && (a->pcid->subsystem_device & ATTO_SSDID_TBT)) |
897 | a->flags2 |= AF2_THUNDERBOLT; | 895 | a->flags2 |= AF2_THUNDERBOLT; |
898 | 896 | ||
899 | if (a->flags2 & AF2_THUNDERBOLT) | 897 | if (test_bit(AF2_THUNDERBOLT, &a->flags2)) |
900 | a->flags2 |= AF2_SERIAL_FLASH; | 898 | a->flags2 |= AF2_SERIAL_FLASH; |
901 | 899 | ||
902 | if (a->pcid->subsystem_device == ATTO_TLSH_1068) | 900 | if (a->pcid->subsystem_device == ATTO_TLSH_1068) |
@@ -956,14 +954,14 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, | |||
956 | a->outbound_copy = (u32 volatile *)high; | 954 | a->outbound_copy = (u32 volatile *)high; |
957 | high += sizeof(u32); | 955 | high += sizeof(u32); |
958 | 956 | ||
959 | if (!(a->flags & AF_NVR_VALID)) | 957 | if (!test_bit(AF_NVR_VALID, &a->flags)) |
960 | esas2r_nvram_set_defaults(a); | 958 | esas2r_nvram_set_defaults(a); |
961 | 959 | ||
962 | /* update the caller's uncached memory area pointer */ | 960 | /* update the caller's uncached memory area pointer */ |
963 | *uncached_area = (void *)high; | 961 | *uncached_area = (void *)high; |
964 | 962 | ||
965 | /* initialize the allocated memory */ | 963 | /* initialize the allocated memory */ |
966 | if (a->flags & AF_FIRST_INIT) { | 964 | if (test_bit(AF_FIRST_INIT, &a->flags)) { |
967 | memset(a->req_table, 0, | 965 | memset(a->req_table, 0, |
968 | (num_requests + num_ae_requests + | 966 | (num_requests + num_ae_requests + |
969 | 1) * sizeof(struct esas2r_request *)); | 967 | 1) * sizeof(struct esas2r_request *)); |
@@ -1019,7 +1017,7 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) | |||
1019 | * if the chip reset detected flag is set, we can bypass a bunch of | 1017 | * if the chip reset detected flag is set, we can bypass a bunch of |
1020 | * stuff. | 1018 | * stuff. |
1021 | */ | 1019 | */ |
1022 | if (a->flags & AF_CHPRST_DETECTED) | 1020 | if (test_bit(AF_CHPRST_DETECTED, &a->flags)) |
1023 | goto skip_chip_reset; | 1021 | goto skip_chip_reset; |
1024 | 1022 | ||
1025 | /* | 1023 | /* |
@@ -1057,14 +1055,12 @@ bool esas2r_check_adapter(struct esas2r_adapter *a) | |||
1057 | doorbell); | 1055 | doorbell); |
1058 | 1056 | ||
1059 | if (ver == DRBL_FW_VER_0) { | 1057 | if (ver == DRBL_FW_VER_0) { |
1060 | esas2r_lock_set_flags(&a->flags, | 1058 | set_bit(AF_LEGACY_SGE_MODE, &a->flags); |
1061 | AF_LEGACY_SGE_MODE); | ||
1062 | 1059 | ||
1063 | a->max_vdareq_size = 128; | 1060 | a->max_vdareq_size = 128; |
1064 | a->build_sgl = esas2r_build_sg_list_sge; | 1061 | a->build_sgl = esas2r_build_sg_list_sge; |
1065 | } else if (ver == DRBL_FW_VER_1) { | 1062 | } else if (ver == DRBL_FW_VER_1) { |
1066 | esas2r_lock_clear_flags(&a->flags, | 1063 | clear_bit(AF_LEGACY_SGE_MODE, &a->flags); |
1067 | AF_LEGACY_SGE_MODE); | ||
1068 | 1064 | ||
1069 | a->max_vdareq_size = 1024; | 1065 | a->max_vdareq_size = 1024; |
1070 | a->build_sgl = esas2r_build_sg_list_prd; | 1066 | a->build_sgl = esas2r_build_sg_list_prd; |
@@ -1139,7 +1135,7 @@ skip_chip_reset: | |||
1139 | *a->outbound_copy = | 1135 | *a->outbound_copy = |
1140 | a->last_write = | 1136 | a->last_write = |
1141 | a->last_read = a->list_size - 1; | 1137 | a->last_read = a->list_size - 1; |
1142 | esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE); | 1138 | set_bit(AF_COMM_LIST_TOGGLE, &a->flags); |
1143 | esas2r_write_register_dword(a, MU_IN_LIST_WRITE, MU_ILW_TOGGLE | | 1139 | esas2r_write_register_dword(a, MU_IN_LIST_WRITE, MU_ILW_TOGGLE | |
1144 | a->last_write); | 1140 | a->last_write); |
1145 | esas2r_write_register_dword(a, MU_OUT_LIST_COPY, MU_OLC_TOGGLE | | 1141 | esas2r_write_register_dword(a, MU_OUT_LIST_COPY, MU_OLC_TOGGLE | |
@@ -1204,9 +1200,9 @@ skip_chip_reset: | |||
1204 | */ | 1200 | */ |
1205 | doorbell = esas2r_read_register_dword(a, MU_DOORBELL_IN_ENB); | 1201 | doorbell = esas2r_read_register_dword(a, MU_DOORBELL_IN_ENB); |
1206 | if (doorbell & DRBL_POWER_DOWN) | 1202 | if (doorbell & DRBL_POWER_DOWN) |
1207 | esas2r_lock_set_flags(&a->flags2, AF2_VDA_POWER_DOWN); | 1203 | set_bit(AF2_VDA_POWER_DOWN, &a->flags2); |
1208 | else | 1204 | else |
1209 | esas2r_lock_clear_flags(&a->flags2, AF2_VDA_POWER_DOWN); | 1205 | clear_bit(AF2_VDA_POWER_DOWN, &a->flags2); |
1210 | 1206 | ||
1211 | /* | 1207 | /* |
1212 | * enable assertion of outbound queue and doorbell interrupts in the | 1208 | * enable assertion of outbound queue and doorbell interrupts in the |
@@ -1239,8 +1235,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, | |||
1239 | 0, | 1235 | 0, |
1240 | NULL); | 1236 | NULL); |
1241 | ci = (struct atto_vda_cfg_init *)&rq->vrq->cfg.data.init; | 1237 | ci = (struct atto_vda_cfg_init *)&rq->vrq->cfg.data.init; |
1242 | ci->sgl_page_size = sgl_page_size; | 1238 | ci->sgl_page_size = cpu_to_le32(sgl_page_size); |
1243 | ci->epoch_time = now.tv_sec; | 1239 | ci->epoch_time = cpu_to_le32(now.tv_sec); |
1244 | rq->flags |= RF_FAILURE_OK; | 1240 | rq->flags |= RF_FAILURE_OK; |
1245 | a->init_msg = ESAS2R_INIT_MSG_INIT; | 1241 | a->init_msg = ESAS2R_INIT_MSG_INIT; |
1246 | break; | 1242 | break; |
@@ -1250,12 +1246,15 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, | |||
1250 | if (rq->req_stat == RS_SUCCESS) { | 1246 | if (rq->req_stat == RS_SUCCESS) { |
1251 | u32 major; | 1247 | u32 major; |
1252 | u32 minor; | 1248 | u32 minor; |
1249 | u16 fw_release; | ||
1253 | 1250 | ||
1254 | a->fw_version = le16_to_cpu( | 1251 | a->fw_version = le16_to_cpu( |
1255 | rq->func_rsp.cfg_rsp.vda_version); | 1252 | rq->func_rsp.cfg_rsp.vda_version); |
1256 | a->fw_build = rq->func_rsp.cfg_rsp.fw_build; | 1253 | a->fw_build = rq->func_rsp.cfg_rsp.fw_build; |
1257 | major = LOBYTE(rq->func_rsp.cfg_rsp.fw_release); | 1254 | fw_release = le16_to_cpu( |
1258 | minor = HIBYTE(rq->func_rsp.cfg_rsp.fw_release); | 1255 | rq->func_rsp.cfg_rsp.fw_release); |
1256 | major = LOBYTE(fw_release); | ||
1257 | minor = HIBYTE(fw_release); | ||
1259 | a->fw_version += (major << 16) + (minor << 24); | 1258 | a->fw_version += (major << 16) + (minor << 24); |
1260 | } else { | 1259 | } else { |
1261 | esas2r_hdebug("FAILED"); | 1260 | esas2r_hdebug("FAILED"); |
@@ -1266,9 +1265,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, | |||
1266 | * unsupported config requests correctly. | 1265 | * unsupported config requests correctly. |
1267 | */ | 1266 | */ |
1268 | 1267 | ||
1269 | if ((a->flags2 & AF2_THUNDERBOLT) | 1268 | if ((test_bit(AF2_THUNDERBOLT, &a->flags2)) |
1270 | || (be32_to_cpu(a->fw_version) > | 1269 | || (be32_to_cpu(a->fw_version) > 0x00524702)) { |
1271 | be32_to_cpu(0x47020052))) { | ||
1272 | esas2r_hdebug("CFG get init"); | 1270 | esas2r_hdebug("CFG get init"); |
1273 | esas2r_build_cfg_req(a, | 1271 | esas2r_build_cfg_req(a, |
1274 | rq, | 1272 | rq, |
@@ -1361,10 +1359,10 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1361 | struct esas2r_request *rq; | 1359 | struct esas2r_request *rq; |
1362 | u32 i; | 1360 | u32 i; |
1363 | 1361 | ||
1364 | if (a->flags & AF_DEGRADED_MODE) | 1362 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1365 | goto exit; | 1363 | goto exit; |
1366 | 1364 | ||
1367 | if (!(a->flags & AF_NVR_VALID)) { | 1365 | if (!test_bit(AF_NVR_VALID, &a->flags)) { |
1368 | if (!esas2r_nvram_read_direct(a)) | 1366 | if (!esas2r_nvram_read_direct(a)) |
1369 | esas2r_log(ESAS2R_LOG_WARN, | 1367 | esas2r_log(ESAS2R_LOG_WARN, |
1370 | "invalid/missing NVRAM parameters"); | 1368 | "invalid/missing NVRAM parameters"); |
@@ -1376,8 +1374,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1376 | } | 1374 | } |
1377 | 1375 | ||
1378 | /* The firmware is ready. */ | 1376 | /* The firmware is ready. */ |
1379 | esas2r_lock_clear_flags(&a->flags, AF_DEGRADED_MODE); | 1377 | clear_bit(AF_DEGRADED_MODE, &a->flags); |
1380 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); | 1378 | clear_bit(AF_CHPRST_PENDING, &a->flags); |
1381 | 1379 | ||
1382 | /* Post all the async event requests */ | 1380 | /* Post all the async event requests */ |
1383 | for (i = 0, rq = a->first_ae_req; i < num_ae_requests; i++, rq++) | 1381 | for (i = 0, rq = a->first_ae_req; i < num_ae_requests; i++, rq++) |
@@ -1398,8 +1396,8 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1398 | 1396 | ||
1399 | esas2r_hdebug("firmware revision: %s", a->fw_rev); | 1397 | esas2r_hdebug("firmware revision: %s", a->fw_rev); |
1400 | 1398 | ||
1401 | if ((a->flags & AF_CHPRST_DETECTED) | 1399 | if (test_bit(AF_CHPRST_DETECTED, &a->flags) |
1402 | && (a->flags & AF_FIRST_INIT)) { | 1400 | && (test_bit(AF_FIRST_INIT, &a->flags))) { |
1403 | esas2r_enable_chip_interrupts(a); | 1401 | esas2r_enable_chip_interrupts(a); |
1404 | return true; | 1402 | return true; |
1405 | } | 1403 | } |
@@ -1423,18 +1421,18 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1423 | * Block Tasklets from getting scheduled and indicate this is | 1421 | * Block Tasklets from getting scheduled and indicate this is |
1424 | * polled discovery. | 1422 | * polled discovery. |
1425 | */ | 1423 | */ |
1426 | esas2r_lock_set_flags(&a->flags, AF_TASKLET_SCHEDULED); | 1424 | set_bit(AF_TASKLET_SCHEDULED, &a->flags); |
1427 | esas2r_lock_set_flags(&a->flags, AF_DISC_POLLED); | 1425 | set_bit(AF_DISC_POLLED, &a->flags); |
1428 | 1426 | ||
1429 | /* | 1427 | /* |
1430 | * Temporarily bring the disable count to zero to enable | 1428 | * Temporarily bring the disable count to zero to enable |
1431 | * deferred processing. Note that the count is already zero | 1429 | * deferred processing. Note that the count is already zero |
1432 | * after the first initialization. | 1430 | * after the first initialization. |
1433 | */ | 1431 | */ |
1434 | if (a->flags & AF_FIRST_INIT) | 1432 | if (test_bit(AF_FIRST_INIT, &a->flags)) |
1435 | atomic_dec(&a->disable_cnt); | 1433 | atomic_dec(&a->disable_cnt); |
1436 | 1434 | ||
1437 | while (a->flags & AF_DISC_PENDING) { | 1435 | while (test_bit(AF_DISC_PENDING, &a->flags)) { |
1438 | schedule_timeout_interruptible(msecs_to_jiffies(100)); | 1436 | schedule_timeout_interruptible(msecs_to_jiffies(100)); |
1439 | 1437 | ||
1440 | /* | 1438 | /* |
@@ -1453,7 +1451,7 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1453 | * we have to make sure the timer tick processes the | 1451 | * we have to make sure the timer tick processes the |
1454 | * doorbell indicating the firmware is ready. | 1452 | * doorbell indicating the firmware is ready. |
1455 | */ | 1453 | */ |
1456 | if (!(a->flags & AF_CHPRST_PENDING)) | 1454 | if (!test_bit(AF_CHPRST_PENDING, &a->flags)) |
1457 | esas2r_disc_check_for_work(a); | 1455 | esas2r_disc_check_for_work(a); |
1458 | 1456 | ||
1459 | /* Simulate a timer tick. */ | 1457 | /* Simulate a timer tick. */ |
@@ -1473,11 +1471,11 @@ bool esas2r_init_adapter_hw(struct esas2r_adapter *a, bool init_poll) | |||
1473 | 1471 | ||
1474 | } | 1472 | } |
1475 | 1473 | ||
1476 | if (a->flags & AF_FIRST_INIT) | 1474 | if (test_bit(AF_FIRST_INIT, &a->flags)) |
1477 | atomic_inc(&a->disable_cnt); | 1475 | atomic_inc(&a->disable_cnt); |
1478 | 1476 | ||
1479 | esas2r_lock_clear_flags(&a->flags, AF_DISC_POLLED); | 1477 | clear_bit(AF_DISC_POLLED, &a->flags); |
1480 | esas2r_lock_clear_flags(&a->flags, AF_TASKLET_SCHEDULED); | 1478 | clear_bit(AF_TASKLET_SCHEDULED, &a->flags); |
1481 | } | 1479 | } |
1482 | 1480 | ||
1483 | 1481 | ||
@@ -1504,26 +1502,26 @@ exit: | |||
1504 | * need to get done before we exit. | 1502 | * need to get done before we exit. |
1505 | */ | 1503 | */ |
1506 | 1504 | ||
1507 | if ((a->flags & AF_CHPRST_DETECTED) | 1505 | if (test_bit(AF_CHPRST_DETECTED, &a->flags) && |
1508 | && (a->flags & AF_FIRST_INIT)) { | 1506 | test_bit(AF_FIRST_INIT, &a->flags)) { |
1509 | /* | 1507 | /* |
1510 | * Reinitialization was performed during the first | 1508 | * Reinitialization was performed during the first |
1511 | * initialization. Only clear the chip reset flag so the | 1509 | * initialization. Only clear the chip reset flag so the |
1512 | * original device polling is not cancelled. | 1510 | * original device polling is not cancelled. |
1513 | */ | 1511 | */ |
1514 | if (!rslt) | 1512 | if (!rslt) |
1515 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); | 1513 | clear_bit(AF_CHPRST_PENDING, &a->flags); |
1516 | } else { | 1514 | } else { |
1517 | /* First initialization or a subsequent re-init is complete. */ | 1515 | /* First initialization or a subsequent re-init is complete. */ |
1518 | if (!rslt) { | 1516 | if (!rslt) { |
1519 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); | 1517 | clear_bit(AF_CHPRST_PENDING, &a->flags); |
1520 | esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); | 1518 | clear_bit(AF_DISC_PENDING, &a->flags); |
1521 | } | 1519 | } |
1522 | 1520 | ||
1523 | 1521 | ||
1524 | /* Enable deferred processing after the first initialization. */ | 1522 | /* Enable deferred processing after the first initialization. */ |
1525 | if (a->flags & AF_FIRST_INIT) { | 1523 | if (test_bit(AF_FIRST_INIT, &a->flags)) { |
1526 | esas2r_lock_clear_flags(&a->flags, AF_FIRST_INIT); | 1524 | clear_bit(AF_FIRST_INIT, &a->flags); |
1527 | 1525 | ||
1528 | if (atomic_dec_return(&a->disable_cnt) == 0) | 1526 | if (atomic_dec_return(&a->disable_cnt) == 0) |
1529 | esas2r_do_deferred_processes(a); | 1527 | esas2r_do_deferred_processes(a); |
@@ -1535,7 +1533,7 @@ exit: | |||
1535 | 1533 | ||
1536 | void esas2r_reset_adapter(struct esas2r_adapter *a) | 1534 | void esas2r_reset_adapter(struct esas2r_adapter *a) |
1537 | { | 1535 | { |
1538 | esas2r_lock_set_flags(&a->flags, AF_OS_RESET); | 1536 | set_bit(AF_OS_RESET, &a->flags); |
1539 | esas2r_local_reset_adapter(a); | 1537 | esas2r_local_reset_adapter(a); |
1540 | esas2r_schedule_tasklet(a); | 1538 | esas2r_schedule_tasklet(a); |
1541 | } | 1539 | } |
@@ -1550,17 +1548,17 @@ void esas2r_reset_chip(struct esas2r_adapter *a) | |||
1550 | * dump is located in the upper 512KB of the onchip SRAM. Make sure | 1548 | * dump is located in the upper 512KB of the onchip SRAM. Make sure |
1551 | * to not overwrite a previous crash that was saved. | 1549 | * to not overwrite a previous crash that was saved. |
1552 | */ | 1550 | */ |
1553 | if ((a->flags2 & AF2_COREDUMP_AVAIL) | 1551 | if (test_bit(AF2_COREDUMP_AVAIL, &a->flags2) && |
1554 | && !(a->flags2 & AF2_COREDUMP_SAVED)) { | 1552 | !test_bit(AF2_COREDUMP_SAVED, &a->flags2)) { |
1555 | esas2r_read_mem_block(a, | 1553 | esas2r_read_mem_block(a, |
1556 | a->fw_coredump_buff, | 1554 | a->fw_coredump_buff, |
1557 | MW_DATA_ADDR_SRAM + 0x80000, | 1555 | MW_DATA_ADDR_SRAM + 0x80000, |
1558 | ESAS2R_FWCOREDUMP_SZ); | 1556 | ESAS2R_FWCOREDUMP_SZ); |
1559 | 1557 | ||
1560 | esas2r_lock_set_flags(&a->flags2, AF2_COREDUMP_SAVED); | 1558 | set_bit(AF2_COREDUMP_SAVED, &a->flags2); |
1561 | } | 1559 | } |
1562 | 1560 | ||
1563 | esas2r_lock_clear_flags(&a->flags2, AF2_COREDUMP_AVAIL); | 1561 | clear_bit(AF2_COREDUMP_AVAIL, &a->flags2); |
1564 | 1562 | ||
1565 | /* Reset the chip */ | 1563 | /* Reset the chip */ |
1566 | if (a->pcid->revision == MVR_FREY_B2) | 1564 | if (a->pcid->revision == MVR_FREY_B2) |
@@ -1606,10 +1604,10 @@ static void esas2r_power_down_notify_firmware(struct esas2r_adapter *a) | |||
1606 | */ | 1604 | */ |
1607 | void esas2r_power_down(struct esas2r_adapter *a) | 1605 | void esas2r_power_down(struct esas2r_adapter *a) |
1608 | { | 1606 | { |
1609 | esas2r_lock_set_flags(&a->flags, AF_POWER_MGT); | 1607 | set_bit(AF_POWER_MGT, &a->flags); |
1610 | esas2r_lock_set_flags(&a->flags, AF_POWER_DOWN); | 1608 | set_bit(AF_POWER_DOWN, &a->flags); |
1611 | 1609 | ||
1612 | if (!(a->flags & AF_DEGRADED_MODE)) { | 1610 | if (!test_bit(AF_DEGRADED_MODE, &a->flags)) { |
1613 | u32 starttime; | 1611 | u32 starttime; |
1614 | u32 doorbell; | 1612 | u32 doorbell; |
1615 | 1613 | ||
@@ -1649,14 +1647,14 @@ void esas2r_power_down(struct esas2r_adapter *a) | |||
1649 | * For versions of firmware that support it tell them the driver | 1647 | * For versions of firmware that support it tell them the driver |
1650 | * is powering down. | 1648 | * is powering down. |
1651 | */ | 1649 | */ |
1652 | if (a->flags2 & AF2_VDA_POWER_DOWN) | 1650 | if (test_bit(AF2_VDA_POWER_DOWN, &a->flags2)) |
1653 | esas2r_power_down_notify_firmware(a); | 1651 | esas2r_power_down_notify_firmware(a); |
1654 | } | 1652 | } |
1655 | 1653 | ||
1656 | /* Suspend I/O processing. */ | 1654 | /* Suspend I/O processing. */ |
1657 | esas2r_lock_set_flags(&a->flags, AF_OS_RESET); | 1655 | set_bit(AF_OS_RESET, &a->flags); |
1658 | esas2r_lock_set_flags(&a->flags, AF_DISC_PENDING); | 1656 | set_bit(AF_DISC_PENDING, &a->flags); |
1659 | esas2r_lock_set_flags(&a->flags, AF_CHPRST_PENDING); | 1657 | set_bit(AF_CHPRST_PENDING, &a->flags); |
1660 | 1658 | ||
1661 | esas2r_process_adapter_reset(a); | 1659 | esas2r_process_adapter_reset(a); |
1662 | 1660 | ||
@@ -1673,9 +1671,9 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll) | |||
1673 | { | 1671 | { |
1674 | bool ret; | 1672 | bool ret; |
1675 | 1673 | ||
1676 | esas2r_lock_clear_flags(&a->flags, AF_POWER_DOWN); | 1674 | clear_bit(AF_POWER_DOWN, &a->flags); |
1677 | esas2r_init_pci_cfg_space(a); | 1675 | esas2r_init_pci_cfg_space(a); |
1678 | esas2r_lock_set_flags(&a->flags, AF_FIRST_INIT); | 1676 | set_bit(AF_FIRST_INIT, &a->flags); |
1679 | atomic_inc(&a->disable_cnt); | 1677 | atomic_inc(&a->disable_cnt); |
1680 | 1678 | ||
1681 | /* reinitialize the adapter */ | 1679 | /* reinitialize the adapter */ |
@@ -1687,17 +1685,17 @@ bool esas2r_power_up(struct esas2r_adapter *a, bool init_poll) | |||
1687 | esas2r_send_reset_ae(a, true); | 1685 | esas2r_send_reset_ae(a, true); |
1688 | 1686 | ||
1689 | /* clear this flag after initialization. */ | 1687 | /* clear this flag after initialization. */ |
1690 | esas2r_lock_clear_flags(&a->flags, AF_POWER_MGT); | 1688 | clear_bit(AF_POWER_MGT, &a->flags); |
1691 | return ret; | 1689 | return ret; |
1692 | } | 1690 | } |
1693 | 1691 | ||
1694 | bool esas2r_is_adapter_present(struct esas2r_adapter *a) | 1692 | bool esas2r_is_adapter_present(struct esas2r_adapter *a) |
1695 | { | 1693 | { |
1696 | if (a->flags & AF_NOT_PRESENT) | 1694 | if (test_bit(AF_NOT_PRESENT, &a->flags)) |
1697 | return false; | 1695 | return false; |
1698 | 1696 | ||
1699 | if (esas2r_read_register_dword(a, MU_DOORBELL_OUT) == 0xFFFFFFFF) { | 1697 | if (esas2r_read_register_dword(a, MU_DOORBELL_OUT) == 0xFFFFFFFF) { |
1700 | esas2r_lock_set_flags(&a->flags, AF_NOT_PRESENT); | 1698 | set_bit(AF_NOT_PRESENT, &a->flags); |
1701 | 1699 | ||
1702 | return false; | 1700 | return false; |
1703 | } | 1701 | } |
diff --git a/drivers/scsi/esas2r/esas2r_int.c b/drivers/scsi/esas2r/esas2r_int.c index c2d4ff57c5c3..f16d6bcf9bb6 100644 --- a/drivers/scsi/esas2r/esas2r_int.c +++ b/drivers/scsi/esas2r/esas2r_int.c | |||
@@ -96,7 +96,7 @@ irqreturn_t esas2r_interrupt(int irq, void *dev_id) | |||
96 | if (!esas2r_adapter_interrupt_pending(a)) | 96 | if (!esas2r_adapter_interrupt_pending(a)) |
97 | return IRQ_NONE; | 97 | return IRQ_NONE; |
98 | 98 | ||
99 | esas2r_lock_set_flags(&a->flags2, AF2_INT_PENDING); | 99 | set_bit(AF2_INT_PENDING, &a->flags2); |
100 | esas2r_schedule_tasklet(a); | 100 | esas2r_schedule_tasklet(a); |
101 | 101 | ||
102 | return IRQ_HANDLED; | 102 | return IRQ_HANDLED; |
@@ -317,9 +317,10 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a) | |||
317 | * = 2 - can start any request | 317 | * = 2 - can start any request |
318 | */ | 318 | */ |
319 | 319 | ||
320 | if (a->flags & (AF_CHPRST_PENDING | AF_FLASHING)) | 320 | if (test_bit(AF_CHPRST_PENDING, &a->flags) || |
321 | test_bit(AF_FLASHING, &a->flags)) | ||
321 | startreqs = 0; | 322 | startreqs = 0; |
322 | else if (a->flags & AF_DISC_PENDING) | 323 | else if (test_bit(AF_DISC_PENDING, &a->flags)) |
323 | startreqs = 1; | 324 | startreqs = 1; |
324 | 325 | ||
325 | atomic_inc(&a->disable_cnt); | 326 | atomic_inc(&a->disable_cnt); |
@@ -367,7 +368,7 @@ void esas2r_do_deferred_processes(struct esas2r_adapter *a) | |||
367 | * Flashing could have been set by last local | 368 | * Flashing could have been set by last local |
368 | * start | 369 | * start |
369 | */ | 370 | */ |
370 | if (a->flags & AF_FLASHING) | 371 | if (test_bit(AF_FLASHING, &a->flags)) |
371 | break; | 372 | break; |
372 | } | 373 | } |
373 | } | 374 | } |
@@ -404,7 +405,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a) | |||
404 | 405 | ||
405 | dc->disc_evt = 0; | 406 | dc->disc_evt = 0; |
406 | 407 | ||
407 | esas2r_lock_clear_flags(&a->flags, AF_DISC_IN_PROG); | 408 | clear_bit(AF_DISC_IN_PROG, &a->flags); |
408 | } | 409 | } |
409 | 410 | ||
410 | /* | 411 | /* |
@@ -425,7 +426,7 @@ void esas2r_process_adapter_reset(struct esas2r_adapter *a) | |||
425 | a->last_write = | 426 | a->last_write = |
426 | a->last_read = a->list_size - 1; | 427 | a->last_read = a->list_size - 1; |
427 | 428 | ||
428 | esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE); | 429 | set_bit(AF_COMM_LIST_TOGGLE, &a->flags); |
429 | 430 | ||
430 | /* Kill all the requests on the active list */ | 431 | /* Kill all the requests on the active list */ |
431 | list_for_each(element, &a->defer_list) { | 432 | list_for_each(element, &a->defer_list) { |
@@ -470,7 +471,7 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a) | |||
470 | if (atomic_read(&a->disable_cnt) == 0) | 471 | if (atomic_read(&a->disable_cnt) == 0) |
471 | esas2r_do_deferred_processes(a); | 472 | esas2r_do_deferred_processes(a); |
472 | 473 | ||
473 | esas2r_lock_clear_flags(&a->flags, AF_OS_RESET); | 474 | clear_bit(AF_OS_RESET, &a->flags); |
474 | 475 | ||
475 | esas2r_trace_exit(); | 476 | esas2r_trace_exit(); |
476 | } | 477 | } |
@@ -478,10 +479,10 @@ static void esas2r_process_bus_reset(struct esas2r_adapter *a) | |||
478 | static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) | 479 | static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) |
479 | { | 480 | { |
480 | 481 | ||
481 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_NEEDED); | 482 | clear_bit(AF_CHPRST_NEEDED, &a->flags); |
482 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED); | 483 | clear_bit(AF_BUSRST_NEEDED, &a->flags); |
483 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED); | 484 | clear_bit(AF_BUSRST_DETECTED, &a->flags); |
484 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING); | 485 | clear_bit(AF_BUSRST_PENDING, &a->flags); |
485 | /* | 486 | /* |
486 | * Make sure we don't get attempt more than 3 resets | 487 | * Make sure we don't get attempt more than 3 resets |
487 | * when the uptime between resets does not exceed one | 488 | * when the uptime between resets does not exceed one |
@@ -507,10 +508,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) | |||
507 | * prevent the heartbeat from trying to recover. | 508 | * prevent the heartbeat from trying to recover. |
508 | */ | 509 | */ |
509 | 510 | ||
510 | esas2r_lock_set_flags(&a->flags, AF_DEGRADED_MODE); | 511 | set_bit(AF_DEGRADED_MODE, &a->flags); |
511 | esas2r_lock_set_flags(&a->flags, AF_DISABLED); | 512 | set_bit(AF_DISABLED, &a->flags); |
512 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_PENDING); | 513 | clear_bit(AF_CHPRST_PENDING, &a->flags); |
513 | esas2r_lock_clear_flags(&a->flags, AF_DISC_PENDING); | 514 | clear_bit(AF_DISC_PENDING, &a->flags); |
514 | 515 | ||
515 | esas2r_disable_chip_interrupts(a); | 516 | esas2r_disable_chip_interrupts(a); |
516 | a->int_mask = 0; | 517 | a->int_mask = 0; |
@@ -519,18 +520,17 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) | |||
519 | esas2r_log(ESAS2R_LOG_CRIT, | 520 | esas2r_log(ESAS2R_LOG_CRIT, |
520 | "Adapter disabled because of hardware failure"); | 521 | "Adapter disabled because of hardware failure"); |
521 | } else { | 522 | } else { |
522 | u32 flags = | 523 | bool alrdyrst = test_and_set_bit(AF_CHPRST_STARTED, &a->flags); |
523 | esas2r_lock_set_flags(&a->flags, AF_CHPRST_STARTED); | ||
524 | 524 | ||
525 | if (!(flags & AF_CHPRST_STARTED)) | 525 | if (!alrdyrst) |
526 | /* | 526 | /* |
527 | * Only disable interrupts if this is | 527 | * Only disable interrupts if this is |
528 | * the first reset attempt. | 528 | * the first reset attempt. |
529 | */ | 529 | */ |
530 | esas2r_disable_chip_interrupts(a); | 530 | esas2r_disable_chip_interrupts(a); |
531 | 531 | ||
532 | if ((a->flags & AF_POWER_MGT) && !(a->flags & AF_FIRST_INIT) && | 532 | if ((test_bit(AF_POWER_MGT, &a->flags)) && |
533 | !(flags & AF_CHPRST_STARTED)) { | 533 | !test_bit(AF_FIRST_INIT, &a->flags) && !alrdyrst) { |
534 | /* | 534 | /* |
535 | * Don't reset the chip on the first | 535 | * Don't reset the chip on the first |
536 | * deferred power up attempt. | 536 | * deferred power up attempt. |
@@ -543,10 +543,10 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) | |||
543 | /* Kick off the reinitialization */ | 543 | /* Kick off the reinitialization */ |
544 | a->chip_uptime += ESAS2R_CHP_UPTIME_CNT; | 544 | a->chip_uptime += ESAS2R_CHP_UPTIME_CNT; |
545 | a->chip_init_time = jiffies_to_msecs(jiffies); | 545 | a->chip_init_time = jiffies_to_msecs(jiffies); |
546 | if (!(a->flags & AF_POWER_MGT)) { | 546 | if (!test_bit(AF_POWER_MGT, &a->flags)) { |
547 | esas2r_process_adapter_reset(a); | 547 | esas2r_process_adapter_reset(a); |
548 | 548 | ||
549 | if (!(flags & AF_CHPRST_STARTED)) { | 549 | if (!alrdyrst) { |
550 | /* Remove devices now that I/O is cleaned up. */ | 550 | /* Remove devices now that I/O is cleaned up. */ |
551 | a->prev_dev_cnt = | 551 | a->prev_dev_cnt = |
552 | esas2r_targ_db_get_tgt_cnt(a); | 552 | esas2r_targ_db_get_tgt_cnt(a); |
@@ -560,38 +560,37 @@ static void esas2r_chip_rst_needed_during_tasklet(struct esas2r_adapter *a) | |||
560 | 560 | ||
561 | static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) | 561 | static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) |
562 | { | 562 | { |
563 | while (a->flags & AF_CHPRST_DETECTED) { | 563 | while (test_bit(AF_CHPRST_DETECTED, &a->flags)) { |
564 | /* | 564 | /* |
565 | * Balance the enable in esas2r_initadapter_hw. | 565 | * Balance the enable in esas2r_initadapter_hw. |
566 | * Esas2r_power_down already took care of it for power | 566 | * Esas2r_power_down already took care of it for power |
567 | * management. | 567 | * management. |
568 | */ | 568 | */ |
569 | if (!(a->flags & AF_DEGRADED_MODE) && !(a->flags & | 569 | if (!test_bit(AF_DEGRADED_MODE, &a->flags) && |
570 | AF_POWER_MGT)) | 570 | !test_bit(AF_POWER_MGT, &a->flags)) |
571 | esas2r_disable_chip_interrupts(a); | 571 | esas2r_disable_chip_interrupts(a); |
572 | 572 | ||
573 | /* Reinitialize the chip. */ | 573 | /* Reinitialize the chip. */ |
574 | esas2r_check_adapter(a); | 574 | esas2r_check_adapter(a); |
575 | esas2r_init_adapter_hw(a, 0); | 575 | esas2r_init_adapter_hw(a, 0); |
576 | 576 | ||
577 | if (a->flags & AF_CHPRST_NEEDED) | 577 | if (test_bit(AF_CHPRST_NEEDED, &a->flags)) |
578 | break; | 578 | break; |
579 | 579 | ||
580 | if (a->flags & AF_POWER_MGT) { | 580 | if (test_bit(AF_POWER_MGT, &a->flags)) { |
581 | /* Recovery from power management. */ | 581 | /* Recovery from power management. */ |
582 | if (a->flags & AF_FIRST_INIT) { | 582 | if (test_bit(AF_FIRST_INIT, &a->flags)) { |
583 | /* Chip reset during normal power up */ | 583 | /* Chip reset during normal power up */ |
584 | esas2r_log(ESAS2R_LOG_CRIT, | 584 | esas2r_log(ESAS2R_LOG_CRIT, |
585 | "The firmware was reset during a normal power-up sequence"); | 585 | "The firmware was reset during a normal power-up sequence"); |
586 | } else { | 586 | } else { |
587 | /* Deferred power up complete. */ | 587 | /* Deferred power up complete. */ |
588 | esas2r_lock_clear_flags(&a->flags, | 588 | clear_bit(AF_POWER_MGT, &a->flags); |
589 | AF_POWER_MGT); | ||
590 | esas2r_send_reset_ae(a, true); | 589 | esas2r_send_reset_ae(a, true); |
591 | } | 590 | } |
592 | } else { | 591 | } else { |
593 | /* Recovery from online chip reset. */ | 592 | /* Recovery from online chip reset. */ |
594 | if (a->flags & AF_FIRST_INIT) { | 593 | if (test_bit(AF_FIRST_INIT, &a->flags)) { |
595 | /* Chip reset during driver load */ | 594 | /* Chip reset during driver load */ |
596 | } else { | 595 | } else { |
597 | /* Chip reset after driver load */ | 596 | /* Chip reset after driver load */ |
@@ -602,14 +601,14 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) | |||
602 | "Recovering from a chip reset while the chip was online"); | 601 | "Recovering from a chip reset while the chip was online"); |
603 | } | 602 | } |
604 | 603 | ||
605 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_STARTED); | 604 | clear_bit(AF_CHPRST_STARTED, &a->flags); |
606 | esas2r_enable_chip_interrupts(a); | 605 | esas2r_enable_chip_interrupts(a); |
607 | 606 | ||
608 | /* | 607 | /* |
609 | * Clear this flag last! this indicates that the chip has been | 608 | * Clear this flag last! this indicates that the chip has been |
610 | * reset already during initialization. | 609 | * reset already during initialization. |
611 | */ | 610 | */ |
612 | esas2r_lock_clear_flags(&a->flags, AF_CHPRST_DETECTED); | 611 | clear_bit(AF_CHPRST_DETECTED, &a->flags); |
613 | } | 612 | } |
614 | } | 613 | } |
615 | 614 | ||
@@ -617,26 +616,28 @@ static void esas2r_handle_chip_rst_during_tasklet(struct esas2r_adapter *a) | |||
617 | /* Perform deferred tasks when chip interrupts are disabled */ | 616 | /* Perform deferred tasks when chip interrupts are disabled */ |
618 | void esas2r_do_tasklet_tasks(struct esas2r_adapter *a) | 617 | void esas2r_do_tasklet_tasks(struct esas2r_adapter *a) |
619 | { | 618 | { |
620 | if (a->flags & (AF_CHPRST_NEEDED | AF_CHPRST_DETECTED)) { | 619 | |
621 | if (a->flags & AF_CHPRST_NEEDED) | 620 | if (test_bit(AF_CHPRST_NEEDED, &a->flags) || |
621 | test_bit(AF_CHPRST_DETECTED, &a->flags)) { | ||
622 | if (test_bit(AF_CHPRST_NEEDED, &a->flags)) | ||
622 | esas2r_chip_rst_needed_during_tasklet(a); | 623 | esas2r_chip_rst_needed_during_tasklet(a); |
623 | 624 | ||
624 | esas2r_handle_chip_rst_during_tasklet(a); | 625 | esas2r_handle_chip_rst_during_tasklet(a); |
625 | } | 626 | } |
626 | 627 | ||
627 | if (a->flags & AF_BUSRST_NEEDED) { | 628 | if (test_bit(AF_BUSRST_NEEDED, &a->flags)) { |
628 | esas2r_hdebug("hard resetting bus"); | 629 | esas2r_hdebug("hard resetting bus"); |
629 | 630 | ||
630 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_NEEDED); | 631 | clear_bit(AF_BUSRST_NEEDED, &a->flags); |
631 | 632 | ||
632 | if (a->flags & AF_FLASHING) | 633 | if (test_bit(AF_FLASHING, &a->flags)) |
633 | esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED); | 634 | set_bit(AF_BUSRST_DETECTED, &a->flags); |
634 | else | 635 | else |
635 | esas2r_write_register_dword(a, MU_DOORBELL_IN, | 636 | esas2r_write_register_dword(a, MU_DOORBELL_IN, |
636 | DRBL_RESET_BUS); | 637 | DRBL_RESET_BUS); |
637 | } | 638 | } |
638 | 639 | ||
639 | if (a->flags & AF_BUSRST_DETECTED) { | 640 | if (test_bit(AF_BUSRST_DETECTED, &a->flags)) { |
640 | esas2r_process_bus_reset(a); | 641 | esas2r_process_bus_reset(a); |
641 | 642 | ||
642 | esas2r_log_dev(ESAS2R_LOG_WARN, | 643 | esas2r_log_dev(ESAS2R_LOG_WARN, |
@@ -645,14 +646,14 @@ void esas2r_do_tasklet_tasks(struct esas2r_adapter *a) | |||
645 | 646 | ||
646 | scsi_report_bus_reset(a->host, 0); | 647 | scsi_report_bus_reset(a->host, 0); |
647 | 648 | ||
648 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_DETECTED); | 649 | clear_bit(AF_BUSRST_DETECTED, &a->flags); |
649 | esas2r_lock_clear_flags(&a->flags, AF_BUSRST_PENDING); | 650 | clear_bit(AF_BUSRST_PENDING, &a->flags); |
650 | 651 | ||
651 | esas2r_log(ESAS2R_LOG_WARN, "Bus reset complete"); | 652 | esas2r_log(ESAS2R_LOG_WARN, "Bus reset complete"); |
652 | } | 653 | } |
653 | 654 | ||
654 | if (a->flags & AF_PORT_CHANGE) { | 655 | if (test_bit(AF_PORT_CHANGE, &a->flags)) { |
655 | esas2r_lock_clear_flags(&a->flags, AF_PORT_CHANGE); | 656 | clear_bit(AF_PORT_CHANGE, &a->flags); |
656 | 657 | ||
657 | esas2r_targ_db_report_changes(a); | 658 | esas2r_targ_db_report_changes(a); |
658 | } | 659 | } |
@@ -672,10 +673,10 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell) | |||
672 | esas2r_write_register_dword(a, MU_DOORBELL_OUT, doorbell); | 673 | esas2r_write_register_dword(a, MU_DOORBELL_OUT, doorbell); |
673 | 674 | ||
674 | if (doorbell & DRBL_RESET_BUS) | 675 | if (doorbell & DRBL_RESET_BUS) |
675 | esas2r_lock_set_flags(&a->flags, AF_BUSRST_DETECTED); | 676 | set_bit(AF_BUSRST_DETECTED, &a->flags); |
676 | 677 | ||
677 | if (doorbell & DRBL_FORCE_INT) | 678 | if (doorbell & DRBL_FORCE_INT) |
678 | esas2r_lock_clear_flags(&a->flags, AF_HEARTBEAT); | 679 | clear_bit(AF_HEARTBEAT, &a->flags); |
679 | 680 | ||
680 | if (doorbell & DRBL_PANIC_REASON_MASK) { | 681 | if (doorbell & DRBL_PANIC_REASON_MASK) { |
681 | esas2r_hdebug("*** Firmware Panic ***"); | 682 | esas2r_hdebug("*** Firmware Panic ***"); |
@@ -683,7 +684,7 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell) | |||
683 | } | 684 | } |
684 | 685 | ||
685 | if (doorbell & DRBL_FW_RESET) { | 686 | if (doorbell & DRBL_FW_RESET) { |
686 | esas2r_lock_set_flags(&a->flags2, AF2_COREDUMP_AVAIL); | 687 | set_bit(AF2_COREDUMP_AVAIL, &a->flags2); |
687 | esas2r_local_reset_adapter(a); | 688 | esas2r_local_reset_adapter(a); |
688 | } | 689 | } |
689 | 690 | ||
@@ -918,7 +919,7 @@ void esas2r_complete_request(struct esas2r_adapter *a, | |||
918 | { | 919 | { |
919 | if (rq->vrq->scsi.function == VDA_FUNC_FLASH | 920 | if (rq->vrq->scsi.function == VDA_FUNC_FLASH |
920 | && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT) | 921 | && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT) |
921 | esas2r_lock_clear_flags(&a->flags, AF_FLASHING); | 922 | clear_bit(AF_FLASHING, &a->flags); |
922 | 923 | ||
923 | /* See if we setup a callback to do special processing */ | 924 | /* See if we setup a callback to do special processing */ |
924 | 925 | ||
diff --git a/drivers/scsi/esas2r/esas2r_io.c b/drivers/scsi/esas2r/esas2r_io.c index 324e2626a08b..a8df916cd57a 100644 --- a/drivers/scsi/esas2r/esas2r_io.c +++ b/drivers/scsi/esas2r/esas2r_io.c | |||
@@ -49,7 +49,8 @@ void esas2r_start_request(struct esas2r_adapter *a, struct esas2r_request *rq) | |||
49 | struct esas2r_request *startrq = rq; | 49 | struct esas2r_request *startrq = rq; |
50 | unsigned long flags; | 50 | unsigned long flags; |
51 | 51 | ||
52 | if (unlikely(a->flags & (AF_DEGRADED_MODE | AF_POWER_DOWN))) { | 52 | if (unlikely(test_bit(AF_DEGRADED_MODE, &a->flags) || |
53 | test_bit(AF_POWER_DOWN, &a->flags))) { | ||
53 | if (rq->vrq->scsi.function == VDA_FUNC_SCSI) | 54 | if (rq->vrq->scsi.function == VDA_FUNC_SCSI) |
54 | rq->req_stat = RS_SEL2; | 55 | rq->req_stat = RS_SEL2; |
55 | else | 56 | else |
@@ -69,8 +70,8 @@ void esas2r_start_request(struct esas2r_adapter *a, struct esas2r_request *rq) | |||
69 | * Note that if AF_DISC_PENDING is set than this will | 70 | * Note that if AF_DISC_PENDING is set than this will |
70 | * go on the defer queue. | 71 | * go on the defer queue. |
71 | */ | 72 | */ |
72 | if (unlikely(t->target_state != TS_PRESENT | 73 | if (unlikely(t->target_state != TS_PRESENT && |
73 | && !(a->flags & AF_DISC_PENDING))) | 74 | !test_bit(AF_DISC_PENDING, &a->flags))) |
74 | rq->req_stat = RS_SEL; | 75 | rq->req_stat = RS_SEL; |
75 | } | 76 | } |
76 | } | 77 | } |
@@ -91,8 +92,9 @@ void esas2r_start_request(struct esas2r_adapter *a, struct esas2r_request *rq) | |||
91 | spin_lock_irqsave(&a->queue_lock, flags); | 92 | spin_lock_irqsave(&a->queue_lock, flags); |
92 | 93 | ||
93 | if (likely(list_empty(&a->defer_list) && | 94 | if (likely(list_empty(&a->defer_list) && |
94 | !(a->flags & | 95 | !test_bit(AF_CHPRST_PENDING, &a->flags) && |
95 | (AF_CHPRST_PENDING | AF_FLASHING | AF_DISC_PENDING)))) | 96 | !test_bit(AF_FLASHING, &a->flags) && |
97 | !test_bit(AF_DISC_PENDING, &a->flags))) | ||
96 | esas2r_local_start_request(a, startrq); | 98 | esas2r_local_start_request(a, startrq); |
97 | else | 99 | else |
98 | list_add_tail(&startrq->req_list, &a->defer_list); | 100 | list_add_tail(&startrq->req_list, &a->defer_list); |
@@ -124,7 +126,7 @@ void esas2r_local_start_request(struct esas2r_adapter *a, | |||
124 | 126 | ||
125 | if (unlikely(rq->vrq->scsi.function == VDA_FUNC_FLASH | 127 | if (unlikely(rq->vrq->scsi.function == VDA_FUNC_FLASH |
126 | && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT)) | 128 | && rq->vrq->flash.sub_func == VDA_FLASH_COMMIT)) |
127 | esas2r_lock_set_flags(&a->flags, AF_FLASHING); | 129 | set_bit(AF_FLASHING, &a->flags); |
128 | 130 | ||
129 | list_add_tail(&rq->req_list, &a->active_list); | 131 | list_add_tail(&rq->req_list, &a->active_list); |
130 | esas2r_start_vda_request(a, rq); | 132 | esas2r_start_vda_request(a, rq); |
@@ -147,11 +149,10 @@ void esas2r_start_vda_request(struct esas2r_adapter *a, | |||
147 | if (a->last_write >= a->list_size) { | 149 | if (a->last_write >= a->list_size) { |
148 | a->last_write = 0; | 150 | a->last_write = 0; |
149 | /* update the toggle bit */ | 151 | /* update the toggle bit */ |
150 | if (a->flags & AF_COMM_LIST_TOGGLE) | 152 | if (test_bit(AF_COMM_LIST_TOGGLE, &a->flags)) |
151 | esas2r_lock_clear_flags(&a->flags, | 153 | clear_bit(AF_COMM_LIST_TOGGLE, &a->flags); |
152 | AF_COMM_LIST_TOGGLE); | ||
153 | else | 154 | else |
154 | esas2r_lock_set_flags(&a->flags, AF_COMM_LIST_TOGGLE); | 155 | set_bit(AF_COMM_LIST_TOGGLE, &a->flags); |
155 | } | 156 | } |
156 | 157 | ||
157 | element = | 158 | element = |
@@ -169,7 +170,7 @@ void esas2r_start_vda_request(struct esas2r_adapter *a, | |||
169 | /* Update the write pointer */ | 170 | /* Update the write pointer */ |
170 | dw = a->last_write; | 171 | dw = a->last_write; |
171 | 172 | ||
172 | if (a->flags & AF_COMM_LIST_TOGGLE) | 173 | if (test_bit(AF_COMM_LIST_TOGGLE, &a->flags)) |
173 | dw |= MU_ILW_TOGGLE; | 174 | dw |= MU_ILW_TOGGLE; |
174 | 175 | ||
175 | esas2r_trace("rq->vrq->scsi.handle:%x", rq->vrq->scsi.handle); | 176 | esas2r_trace("rq->vrq->scsi.handle:%x", rq->vrq->scsi.handle); |
@@ -687,18 +688,14 @@ static void esas2r_handle_pending_reset(struct esas2r_adapter *a, u32 currtime) | |||
687 | esas2r_write_register_dword(a, MU_DOORBELL_OUT, | 688 | esas2r_write_register_dword(a, MU_DOORBELL_OUT, |
688 | doorbell); | 689 | doorbell); |
689 | if (ver == DRBL_FW_VER_0) { | 690 | if (ver == DRBL_FW_VER_0) { |
690 | esas2r_lock_set_flags(&a->flags, | 691 | set_bit(AF_CHPRST_DETECTED, &a->flags); |
691 | AF_CHPRST_DETECTED); | 692 | set_bit(AF_LEGACY_SGE_MODE, &a->flags); |
692 | esas2r_lock_set_flags(&a->flags, | ||
693 | AF_LEGACY_SGE_MODE); | ||
694 | 693 | ||
695 | a->max_vdareq_size = 128; | 694 | a->max_vdareq_size = 128; |
696 | a->build_sgl = esas2r_build_sg_list_sge; | 695 | a->build_sgl = esas2r_build_sg_list_sge; |
697 | } else if (ver == DRBL_FW_VER_1) { | 696 | } else if (ver == DRBL_FW_VER_1) { |
698 | esas2r_lock_set_flags(&a->flags, | 697 | set_bit(AF_CHPRST_DETECTED, &a->flags); |
699 | AF_CHPRST_DETECTED); | 698 | clear_bit(AF_LEGACY_SGE_MODE, &a->flags); |
700 | esas2r_lock_clear_flags(&a->flags, | ||
701 | AF_LEGACY_SGE_MODE); | ||
702 | 699 | ||
703 | a->max_vdareq_size = 1024; | 700 | a->max_vdareq_size = 1024; |
704 | a->build_sgl = esas2r_build_sg_list_prd; | 701 | a->build_sgl = esas2r_build_sg_list_prd; |
@@ -719,28 +716,27 @@ void esas2r_timer_tick(struct esas2r_adapter *a) | |||
719 | a->last_tick_time = currtime; | 716 | a->last_tick_time = currtime; |
720 | 717 | ||
721 | /* count down the uptime */ | 718 | /* count down the uptime */ |
722 | if (a->chip_uptime | 719 | if (a->chip_uptime && |
723 | && !(a->flags & (AF_CHPRST_PENDING | AF_DISC_PENDING))) { | 720 | !test_bit(AF_CHPRST_PENDING, &a->flags) && |
721 | !test_bit(AF_DISC_PENDING, &a->flags)) { | ||
724 | if (deltatime >= a->chip_uptime) | 722 | if (deltatime >= a->chip_uptime) |
725 | a->chip_uptime = 0; | 723 | a->chip_uptime = 0; |
726 | else | 724 | else |
727 | a->chip_uptime -= deltatime; | 725 | a->chip_uptime -= deltatime; |
728 | } | 726 | } |
729 | 727 | ||
730 | if (a->flags & AF_CHPRST_PENDING) { | 728 | if (test_bit(AF_CHPRST_PENDING, &a->flags)) { |
731 | if (!(a->flags & AF_CHPRST_NEEDED) | 729 | if (!test_bit(AF_CHPRST_NEEDED, &a->flags) && |
732 | && !(a->flags & AF_CHPRST_DETECTED)) | 730 | !test_bit(AF_CHPRST_DETECTED, &a->flags)) |
733 | esas2r_handle_pending_reset(a, currtime); | 731 | esas2r_handle_pending_reset(a, currtime); |
734 | } else { | 732 | } else { |
735 | if (a->flags & AF_DISC_PENDING) | 733 | if (test_bit(AF_DISC_PENDING, &a->flags)) |
736 | esas2r_disc_check_complete(a); | 734 | esas2r_disc_check_complete(a); |
737 | 735 | if (test_bit(AF_HEARTBEAT_ENB, &a->flags)) { | |
738 | if (a->flags & AF_HEARTBEAT_ENB) { | 736 | if (test_bit(AF_HEARTBEAT, &a->flags)) { |
739 | if (a->flags & AF_HEARTBEAT) { | ||
740 | if ((currtime - a->heartbeat_time) >= | 737 | if ((currtime - a->heartbeat_time) >= |
741 | ESAS2R_HEARTBEAT_TIME) { | 738 | ESAS2R_HEARTBEAT_TIME) { |
742 | esas2r_lock_clear_flags(&a->flags, | 739 | clear_bit(AF_HEARTBEAT, &a->flags); |
743 | AF_HEARTBEAT); | ||
744 | esas2r_hdebug("heartbeat failed"); | 740 | esas2r_hdebug("heartbeat failed"); |
745 | esas2r_log(ESAS2R_LOG_CRIT, | 741 | esas2r_log(ESAS2R_LOG_CRIT, |
746 | "heartbeat failed"); | 742 | "heartbeat failed"); |
@@ -748,7 +744,7 @@ void esas2r_timer_tick(struct esas2r_adapter *a) | |||
748 | esas2r_local_reset_adapter(a); | 744 | esas2r_local_reset_adapter(a); |
749 | } | 745 | } |
750 | } else { | 746 | } else { |
751 | esas2r_lock_set_flags(&a->flags, AF_HEARTBEAT); | 747 | set_bit(AF_HEARTBEAT, &a->flags); |
752 | a->heartbeat_time = currtime; | 748 | a->heartbeat_time = currtime; |
753 | esas2r_force_interrupt(a); | 749 | esas2r_force_interrupt(a); |
754 | } | 750 | } |
@@ -812,7 +808,7 @@ bool esas2r_send_task_mgmt(struct esas2r_adapter *a, | |||
812 | rqaux->vrq->scsi.flags |= | 808 | rqaux->vrq->scsi.flags |= |
813 | cpu_to_le16(task_mgt_func * LOBIT(FCP_CMND_TM_MASK)); | 809 | cpu_to_le16(task_mgt_func * LOBIT(FCP_CMND_TM_MASK)); |
814 | 810 | ||
815 | if (a->flags & AF_FLASHING) { | 811 | if (test_bit(AF_FLASHING, &a->flags)) { |
816 | /* Assume success. if there are active requests, return busy */ | 812 | /* Assume success. if there are active requests, return busy */ |
817 | rqaux->req_stat = RS_SUCCESS; | 813 | rqaux->req_stat = RS_SUCCESS; |
818 | 814 | ||
@@ -831,7 +827,7 @@ bool esas2r_send_task_mgmt(struct esas2r_adapter *a, | |||
831 | 827 | ||
832 | spin_unlock_irqrestore(&a->queue_lock, flags); | 828 | spin_unlock_irqrestore(&a->queue_lock, flags); |
833 | 829 | ||
834 | if (!(a->flags & AF_FLASHING)) | 830 | if (!test_bit(AF_FLASHING, &a->flags)) |
835 | esas2r_start_request(a, rqaux); | 831 | esas2r_start_request(a, rqaux); |
836 | 832 | ||
837 | esas2r_comp_list_drain(a, &comp_list); | 833 | esas2r_comp_list_drain(a, &comp_list); |
@@ -848,11 +844,12 @@ void esas2r_reset_bus(struct esas2r_adapter *a) | |||
848 | { | 844 | { |
849 | esas2r_log(ESAS2R_LOG_INFO, "performing a bus reset"); | 845 | esas2r_log(ESAS2R_LOG_INFO, "performing a bus reset"); |
850 | 846 | ||
851 | if (!(a->flags & AF_DEGRADED_MODE) | 847 | if (!test_bit(AF_DEGRADED_MODE, &a->flags) && |
852 | && !(a->flags & (AF_CHPRST_PENDING | AF_DISC_PENDING))) { | 848 | !test_bit(AF_CHPRST_PENDING, &a->flags) && |
853 | esas2r_lock_set_flags(&a->flags, AF_BUSRST_NEEDED); | 849 | !test_bit(AF_DISC_PENDING, &a->flags)) { |
854 | esas2r_lock_set_flags(&a->flags, AF_BUSRST_PENDING); | 850 | set_bit(AF_BUSRST_NEEDED, &a->flags); |
855 | esas2r_lock_set_flags(&a->flags, AF_OS_RESET); | 851 | set_bit(AF_BUSRST_PENDING, &a->flags); |
852 | set_bit(AF_OS_RESET, &a->flags); | ||
856 | 853 | ||
857 | esas2r_schedule_tasklet(a); | 854 | esas2r_schedule_tasklet(a); |
858 | } | 855 | } |
diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c index e5b09027e066..d89a0277a8e1 100644 --- a/drivers/scsi/esas2r/esas2r_ioctl.c +++ b/drivers/scsi/esas2r/esas2r_ioctl.c | |||
@@ -347,7 +347,7 @@ static bool csmi_ioctl_tunnel(struct esas2r_adapter *a, | |||
347 | { | 347 | { |
348 | struct atto_vda_ioctl_req *ioctl = &rq->vrq->ioctl; | 348 | struct atto_vda_ioctl_req *ioctl = &rq->vrq->ioctl; |
349 | 349 | ||
350 | if (a->flags & AF_DEGRADED_MODE) | 350 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
351 | return false; | 351 | return false; |
352 | 352 | ||
353 | esas2r_sgc_init(sgc, a, rq, rq->vrq->ioctl.sge); | 353 | esas2r_sgc_init(sgc, a, rq, rq->vrq->ioctl.sge); |
@@ -463,7 +463,7 @@ static int csmi_ioctl_callback(struct esas2r_adapter *a, | |||
463 | gcc->bios_minor_rev = LOBYTE(HIWORD(a->flash_ver)); | 463 | gcc->bios_minor_rev = LOBYTE(HIWORD(a->flash_ver)); |
464 | gcc->bios_build_rev = LOWORD(a->flash_ver); | 464 | gcc->bios_build_rev = LOWORD(a->flash_ver); |
465 | 465 | ||
466 | if (a->flags2 & AF2_THUNDERLINK) | 466 | if (test_bit(AF2_THUNDERLINK, &a->flags2)) |
467 | gcc->cntlr_flags = CSMI_CNTLRF_SAS_HBA | 467 | gcc->cntlr_flags = CSMI_CNTLRF_SAS_HBA |
468 | | CSMI_CNTLRF_SATA_HBA; | 468 | | CSMI_CNTLRF_SATA_HBA; |
469 | else | 469 | else |
@@ -485,7 +485,7 @@ static int csmi_ioctl_callback(struct esas2r_adapter *a, | |||
485 | { | 485 | { |
486 | struct atto_csmi_get_cntlr_sts *gcs = &ioctl_csmi->cntlr_sts; | 486 | struct atto_csmi_get_cntlr_sts *gcs = &ioctl_csmi->cntlr_sts; |
487 | 487 | ||
488 | if (a->flags & AF_DEGRADED_MODE) | 488 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
489 | gcs->status = CSMI_CNTLR_STS_FAILED; | 489 | gcs->status = CSMI_CNTLR_STS_FAILED; |
490 | else | 490 | else |
491 | gcs->status = CSMI_CNTLR_STS_GOOD; | 491 | gcs->status = CSMI_CNTLR_STS_GOOD; |
@@ -819,10 +819,10 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
819 | 819 | ||
820 | gai->adap_type = ATTO_GAI_AT_ESASRAID2; | 820 | gai->adap_type = ATTO_GAI_AT_ESASRAID2; |
821 | 821 | ||
822 | if (a->flags2 & AF2_THUNDERLINK) | 822 | if (test_bit(AF2_THUNDERLINK, &a->flags2)) |
823 | gai->adap_type = ATTO_GAI_AT_TLSASHBA; | 823 | gai->adap_type = ATTO_GAI_AT_TLSASHBA; |
824 | 824 | ||
825 | if (a->flags & AF_DEGRADED_MODE) | 825 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
826 | gai->adap_flags |= ATTO_GAI_AF_DEGRADED; | 826 | gai->adap_flags |= ATTO_GAI_AF_DEGRADED; |
827 | 827 | ||
828 | gai->adap_flags |= ATTO_GAI_AF_SPT_SUPP | | 828 | gai->adap_flags |= ATTO_GAI_AF_SPT_SUPP | |
@@ -938,7 +938,7 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
938 | u32 total_len = ESAS2R_FWCOREDUMP_SZ; | 938 | u32 total_len = ESAS2R_FWCOREDUMP_SZ; |
939 | 939 | ||
940 | /* Size is zero if a core dump isn't present */ | 940 | /* Size is zero if a core dump isn't present */ |
941 | if (!(a->flags2 & AF2_COREDUMP_SAVED)) | 941 | if (!test_bit(AF2_COREDUMP_SAVED, &a->flags2)) |
942 | total_len = 0; | 942 | total_len = 0; |
943 | 943 | ||
944 | if (len > total_len) | 944 | if (len > total_len) |
@@ -960,8 +960,7 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
960 | memset(a->fw_coredump_buff, 0, | 960 | memset(a->fw_coredump_buff, 0, |
961 | ESAS2R_FWCOREDUMP_SZ); | 961 | ESAS2R_FWCOREDUMP_SZ); |
962 | 962 | ||
963 | esas2r_lock_clear_flags(&a->flags2, | 963 | clear_bit(AF2_COREDUMP_SAVED, &a->flags2); |
964 | AF2_COREDUMP_SAVED); | ||
965 | } else if (trc->trace_func != ATTO_TRC_TF_GET_INFO) { | 964 | } else if (trc->trace_func != ATTO_TRC_TF_GET_INFO) { |
966 | hi->status = ATTO_STS_UNSUPPORTED; | 965 | hi->status = ATTO_STS_UNSUPPORTED; |
967 | break; | 966 | break; |
@@ -973,7 +972,7 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
973 | trc->total_length = ESAS2R_FWCOREDUMP_SZ; | 972 | trc->total_length = ESAS2R_FWCOREDUMP_SZ; |
974 | 973 | ||
975 | /* Return zero length buffer if core dump not present */ | 974 | /* Return zero length buffer if core dump not present */ |
976 | if (!(a->flags2 & AF2_COREDUMP_SAVED)) | 975 | if (!test_bit(AF2_COREDUMP_SAVED, &a->flags2)) |
977 | trc->total_length = 0; | 976 | trc->total_length = 0; |
978 | } else { | 977 | } else { |
979 | hi->status = ATTO_STS_UNSUPPORTED; | 978 | hi->status = ATTO_STS_UNSUPPORTED; |
@@ -1048,6 +1047,7 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
1048 | else if (spt->flags & ATTO_SPTF_HEAD_OF_Q) | 1047 | else if (spt->flags & ATTO_SPTF_HEAD_OF_Q) |
1049 | rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_TA_HEAD_Q); | 1048 | rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_TA_HEAD_Q); |
1050 | 1049 | ||
1050 | |||
1051 | if (!esas2r_build_sg_list(a, rq, sgc)) { | 1051 | if (!esas2r_build_sg_list(a, rq, sgc)) { |
1052 | hi->status = ATTO_STS_OUT_OF_RSRC; | 1052 | hi->status = ATTO_STS_OUT_OF_RSRC; |
1053 | break; | 1053 | break; |
@@ -1139,15 +1139,15 @@ static int hba_ioctl_callback(struct esas2r_adapter *a, | |||
1139 | break; | 1139 | break; |
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | if (a->flags & AF_CHPRST_NEEDED) | 1142 | if (test_bit(AF_CHPRST_NEEDED, &a->flags)) |
1143 | ac->adap_state = ATTO_AC_AS_RST_SCHED; | 1143 | ac->adap_state = ATTO_AC_AS_RST_SCHED; |
1144 | else if (a->flags & AF_CHPRST_PENDING) | 1144 | else if (test_bit(AF_CHPRST_PENDING, &a->flags)) |
1145 | ac->adap_state = ATTO_AC_AS_RST_IN_PROG; | 1145 | ac->adap_state = ATTO_AC_AS_RST_IN_PROG; |
1146 | else if (a->flags & AF_DISC_PENDING) | 1146 | else if (test_bit(AF_DISC_PENDING, &a->flags)) |
1147 | ac->adap_state = ATTO_AC_AS_RST_DISC; | 1147 | ac->adap_state = ATTO_AC_AS_RST_DISC; |
1148 | else if (a->flags & AF_DISABLED) | 1148 | else if (test_bit(AF_DISABLED, &a->flags)) |
1149 | ac->adap_state = ATTO_AC_AS_DISABLED; | 1149 | ac->adap_state = ATTO_AC_AS_DISABLED; |
1150 | else if (a->flags & AF_DEGRADED_MODE) | 1150 | else if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1151 | ac->adap_state = ATTO_AC_AS_DEGRADED; | 1151 | ac->adap_state = ATTO_AC_AS_DEGRADED; |
1152 | else | 1152 | else |
1153 | ac->adap_state = ATTO_AC_AS_OK; | 1153 | ac->adap_state = ATTO_AC_AS_OK; |
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 4abf1272e1eb..f37f3e3dd5d5 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c | |||
@@ -889,7 +889,7 @@ int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
889 | /* Assume success, if it fails we will fix the result later. */ | 889 | /* Assume success, if it fails we will fix the result later. */ |
890 | cmd->result = DID_OK << 16; | 890 | cmd->result = DID_OK << 16; |
891 | 891 | ||
892 | if (unlikely(a->flags & AF_DEGRADED_MODE)) { | 892 | if (unlikely(test_bit(AF_DEGRADED_MODE, &a->flags))) { |
893 | cmd->result = DID_NO_CONNECT << 16; | 893 | cmd->result = DID_NO_CONNECT << 16; |
894 | cmd->scsi_done(cmd); | 894 | cmd->scsi_done(cmd); |
895 | return 0; | 895 | return 0; |
@@ -1050,7 +1050,7 @@ int esas2r_eh_abort(struct scsi_cmnd *cmd) | |||
1050 | 1050 | ||
1051 | esas2r_log(ESAS2R_LOG_INFO, "eh_abort (%p)", cmd); | 1051 | esas2r_log(ESAS2R_LOG_INFO, "eh_abort (%p)", cmd); |
1052 | 1052 | ||
1053 | if (a->flags & AF_DEGRADED_MODE) { | 1053 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) { |
1054 | cmd->result = DID_ABORT << 16; | 1054 | cmd->result = DID_ABORT << 16; |
1055 | 1055 | ||
1056 | scsi_set_resid(cmd, 0); | 1056 | scsi_set_resid(cmd, 0); |
@@ -1131,7 +1131,7 @@ static int esas2r_host_bus_reset(struct scsi_cmnd *cmd, bool host_reset) | |||
1131 | struct esas2r_adapter *a = | 1131 | struct esas2r_adapter *a = |
1132 | (struct esas2r_adapter *)cmd->device->host->hostdata; | 1132 | (struct esas2r_adapter *)cmd->device->host->hostdata; |
1133 | 1133 | ||
1134 | if (a->flags & AF_DEGRADED_MODE) | 1134 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1135 | return FAILED; | 1135 | return FAILED; |
1136 | 1136 | ||
1137 | if (host_reset) | 1137 | if (host_reset) |
@@ -1141,14 +1141,14 @@ static int esas2r_host_bus_reset(struct scsi_cmnd *cmd, bool host_reset) | |||
1141 | 1141 | ||
1142 | /* above call sets the AF_OS_RESET flag. wait for it to clear. */ | 1142 | /* above call sets the AF_OS_RESET flag. wait for it to clear. */ |
1143 | 1143 | ||
1144 | while (a->flags & AF_OS_RESET) { | 1144 | while (test_bit(AF_OS_RESET, &a->flags)) { |
1145 | msleep(10); | 1145 | msleep(10); |
1146 | 1146 | ||
1147 | if (a->flags & AF_DEGRADED_MODE) | 1147 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1148 | return FAILED; | 1148 | return FAILED; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | if (a->flags & AF_DEGRADED_MODE) | 1151 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1152 | return FAILED; | 1152 | return FAILED; |
1153 | 1153 | ||
1154 | return SUCCESS; | 1154 | return SUCCESS; |
@@ -1176,7 +1176,7 @@ static int esas2r_dev_targ_reset(struct scsi_cmnd *cmd, bool target_reset) | |||
1176 | u8 task_management_status = RS_PENDING; | 1176 | u8 task_management_status = RS_PENDING; |
1177 | bool completed; | 1177 | bool completed; |
1178 | 1178 | ||
1179 | if (a->flags & AF_DEGRADED_MODE) | 1179 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1180 | return FAILED; | 1180 | return FAILED; |
1181 | 1181 | ||
1182 | retry: | 1182 | retry: |
@@ -1229,7 +1229,7 @@ retry: | |||
1229 | msleep(10); | 1229 | msleep(10); |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | if (a->flags & AF_DEGRADED_MODE) | 1232 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) |
1233 | return FAILED; | 1233 | return FAILED; |
1234 | 1234 | ||
1235 | if (task_management_status == RS_BUSY) { | 1235 | if (task_management_status == RS_BUSY) { |
@@ -1666,13 +1666,13 @@ void esas2r_adapter_tasklet(unsigned long context) | |||
1666 | { | 1666 | { |
1667 | struct esas2r_adapter *a = (struct esas2r_adapter *)context; | 1667 | struct esas2r_adapter *a = (struct esas2r_adapter *)context; |
1668 | 1668 | ||
1669 | if (unlikely(a->flags2 & AF2_TIMER_TICK)) { | 1669 | if (unlikely(test_bit(AF2_TIMER_TICK, &a->flags2))) { |
1670 | esas2r_lock_clear_flags(&a->flags2, AF2_TIMER_TICK); | 1670 | clear_bit(AF2_TIMER_TICK, &a->flags2); |
1671 | esas2r_timer_tick(a); | 1671 | esas2r_timer_tick(a); |
1672 | } | 1672 | } |
1673 | 1673 | ||
1674 | if (likely(a->flags2 & AF2_INT_PENDING)) { | 1674 | if (likely(test_bit(AF2_INT_PENDING, &a->flags2))) { |
1675 | esas2r_lock_clear_flags(&a->flags2, AF2_INT_PENDING); | 1675 | clear_bit(AF2_INT_PENDING, &a->flags2); |
1676 | esas2r_adapter_interrupt(a); | 1676 | esas2r_adapter_interrupt(a); |
1677 | } | 1677 | } |
1678 | 1678 | ||
@@ -1680,12 +1680,12 @@ void esas2r_adapter_tasklet(unsigned long context) | |||
1680 | esas2r_do_tasklet_tasks(a); | 1680 | esas2r_do_tasklet_tasks(a); |
1681 | 1681 | ||
1682 | if (esas2r_is_tasklet_pending(a) | 1682 | if (esas2r_is_tasklet_pending(a) |
1683 | || (a->flags2 & AF2_INT_PENDING) | 1683 | || (test_bit(AF2_INT_PENDING, &a->flags2)) |
1684 | || (a->flags2 & AF2_TIMER_TICK)) { | 1684 | || (test_bit(AF2_TIMER_TICK, &a->flags2))) { |
1685 | esas2r_lock_clear_flags(&a->flags, AF_TASKLET_SCHEDULED); | 1685 | clear_bit(AF_TASKLET_SCHEDULED, &a->flags); |
1686 | esas2r_schedule_tasklet(a); | 1686 | esas2r_schedule_tasklet(a); |
1687 | } else { | 1687 | } else { |
1688 | esas2r_lock_clear_flags(&a->flags, AF_TASKLET_SCHEDULED); | 1688 | clear_bit(AF_TASKLET_SCHEDULED, &a->flags); |
1689 | } | 1689 | } |
1690 | } | 1690 | } |
1691 | 1691 | ||
@@ -1707,7 +1707,7 @@ static void esas2r_timer_callback(unsigned long context) | |||
1707 | { | 1707 | { |
1708 | struct esas2r_adapter *a = (struct esas2r_adapter *)context; | 1708 | struct esas2r_adapter *a = (struct esas2r_adapter *)context; |
1709 | 1709 | ||
1710 | esas2r_lock_set_flags(&a->flags2, AF2_TIMER_TICK); | 1710 | set_bit(AF2_TIMER_TICK, &a->flags2); |
1711 | 1711 | ||
1712 | esas2r_schedule_tasklet(a); | 1712 | esas2r_schedule_tasklet(a); |
1713 | 1713 | ||
diff --git a/drivers/scsi/esas2r/esas2r_targdb.c b/drivers/scsi/esas2r/esas2r_targdb.c index e540a2fa3d15..bf45beaad439 100644 --- a/drivers/scsi/esas2r/esas2r_targdb.c +++ b/drivers/scsi/esas2r/esas2r_targdb.c | |||
@@ -86,7 +86,7 @@ void esas2r_targ_db_report_changes(struct esas2r_adapter *a) | |||
86 | 86 | ||
87 | esas2r_trace_enter(); | 87 | esas2r_trace_enter(); |
88 | 88 | ||
89 | if (a->flags & AF_DISC_PENDING) { | 89 | if (test_bit(AF_DISC_PENDING, &a->flags)) { |
90 | esas2r_trace_exit(); | 90 | esas2r_trace_exit(); |
91 | return; | 91 | return; |
92 | } | 92 | } |
diff --git a/drivers/scsi/esas2r/esas2r_vda.c b/drivers/scsi/esas2r/esas2r_vda.c index fd1392879647..30028e56df63 100644 --- a/drivers/scsi/esas2r/esas2r_vda.c +++ b/drivers/scsi/esas2r/esas2r_vda.c | |||
@@ -84,7 +84,7 @@ bool esas2r_process_vda_ioctl(struct esas2r_adapter *a, | |||
84 | return false; | 84 | return false; |
85 | } | 85 | } |
86 | 86 | ||
87 | if (a->flags & AF_DEGRADED_MODE) { | 87 | if (test_bit(AF_DEGRADED_MODE, &a->flags)) { |
88 | vi->status = ATTO_STS_DEGRADED; | 88 | vi->status = ATTO_STS_DEGRADED; |
89 | return false; | 89 | return false; |
90 | } | 90 | } |
@@ -310,9 +310,9 @@ static void esas2r_complete_vda_ioctl(struct esas2r_adapter *a, | |||
310 | le32_to_cpu(rsp->vda_version); | 310 | le32_to_cpu(rsp->vda_version); |
311 | cfg->data.init.fw_build = rsp->fw_build; | 311 | cfg->data.init.fw_build = rsp->fw_build; |
312 | 312 | ||
313 | snprintf(buf, sizeof(buf), "%1d.%02d", | 313 | snprintf(buf, sizeof(buf), "%1.1u.%2.2u", |
314 | (int)LOBYTE(le16_to_cpu(rsp->fw_release)), | 314 | (int)LOBYTE(le16_to_cpu(rsp->fw_release)), |
315 | (int)HIBYTE(le16_to_cpu(rsp->fw_release))); | 315 | (int)HIBYTE(le16_to_cpu(rsp->fw_release))); |
316 | 316 | ||
317 | memcpy(&cfg->data.init.fw_release, buf, | 317 | memcpy(&cfg->data.init.fw_release, buf, |
318 | sizeof(cfg->data.init.fw_release)); | 318 | sizeof(cfg->data.init.fw_release)); |
@@ -389,7 +389,7 @@ void esas2r_build_mgt_req(struct esas2r_adapter *a, | |||
389 | vrq->length = cpu_to_le32(length); | 389 | vrq->length = cpu_to_le32(length); |
390 | 390 | ||
391 | if (vrq->length) { | 391 | if (vrq->length) { |
392 | if (a->flags & AF_LEGACY_SGE_MODE) { | 392 | if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) { |
393 | vrq->sg_list_offset = (u8)offsetof( | 393 | vrq->sg_list_offset = (u8)offsetof( |
394 | struct atto_vda_mgmt_req, sge); | 394 | struct atto_vda_mgmt_req, sge); |
395 | 395 | ||
@@ -427,7 +427,7 @@ void esas2r_build_ae_req(struct esas2r_adapter *a, struct esas2r_request *rq) | |||
427 | 427 | ||
428 | vrq->length = cpu_to_le32(sizeof(struct atto_vda_ae_data)); | 428 | vrq->length = cpu_to_le32(sizeof(struct atto_vda_ae_data)); |
429 | 429 | ||
430 | if (a->flags & AF_LEGACY_SGE_MODE) { | 430 | if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) { |
431 | vrq->sg_list_offset = | 431 | vrq->sg_list_offset = |
432 | (u8)offsetof(struct atto_vda_ae_req, sge); | 432 | (u8)offsetof(struct atto_vda_ae_req, sge); |
433 | vrq->sge[0].length = cpu_to_le32(SGE_LAST | vrq->length); | 433 | vrq->sge[0].length = cpu_to_le32(SGE_LAST | vrq->length); |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 07453bbf05e7..f3170008ae71 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -408,6 +408,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, | |||
408 | } | 408 | } |
409 | 409 | ||
410 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); | 410 | ctlr = fcoe_ctlr_device_priv(ctlr_dev); |
411 | ctlr->cdev = ctlr_dev; | ||
411 | fcoe = fcoe_ctlr_priv(ctlr); | 412 | fcoe = fcoe_ctlr_priv(ctlr); |
412 | 413 | ||
413 | dev_hold(netdev); | 414 | dev_hold(netdev); |
@@ -1440,22 +1441,28 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1440 | ctlr = fcoe_to_ctlr(fcoe); | 1441 | ctlr = fcoe_to_ctlr(fcoe); |
1441 | lport = ctlr->lp; | 1442 | lport = ctlr->lp; |
1442 | if (unlikely(!lport)) { | 1443 | if (unlikely(!lport)) { |
1443 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); | 1444 | FCOE_NETDEV_DBG(netdev, "Cannot find hba structure\n"); |
1444 | goto err2; | 1445 | goto err2; |
1445 | } | 1446 | } |
1446 | if (!lport->link_up) | 1447 | if (!lport->link_up) |
1447 | goto err2; | 1448 | goto err2; |
1448 | 1449 | ||
1449 | FCOE_NETDEV_DBG(netdev, "skb_info: len:%d data_len:%d head:%p " | 1450 | FCOE_NETDEV_DBG(netdev, |
1450 | "data:%p tail:%p end:%p sum:%d dev:%s", | 1451 | "skb_info: len:%d data_len:%d head:%p data:%p tail:%p end:%p sum:%d dev:%s\n", |
1451 | skb->len, skb->data_len, skb->head, skb->data, | 1452 | skb->len, skb->data_len, skb->head, skb->data, |
1452 | skb_tail_pointer(skb), skb_end_pointer(skb), | 1453 | skb_tail_pointer(skb), skb_end_pointer(skb), |
1453 | skb->csum, skb->dev ? skb->dev->name : "<NULL>"); | 1454 | skb->csum, skb->dev ? skb->dev->name : "<NULL>"); |
1454 | 1455 | ||
1456 | |||
1457 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
1458 | |||
1459 | if (skb == NULL) | ||
1460 | return NET_RX_DROP; | ||
1461 | |||
1455 | eh = eth_hdr(skb); | 1462 | eh = eth_hdr(skb); |
1456 | 1463 | ||
1457 | if (is_fip_mode(ctlr) && | 1464 | if (is_fip_mode(ctlr) && |
1458 | compare_ether_addr(eh->h_source, ctlr->dest_addr)) { | 1465 | !ether_addr_equal(eh->h_source, ctlr->dest_addr)) { |
1459 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", | 1466 | FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", |
1460 | eh->h_source); | 1467 | eh->h_source); |
1461 | goto err; | 1468 | goto err; |
@@ -1540,13 +1547,13 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, | |||
1540 | wake_up_process(fps->thread); | 1547 | wake_up_process(fps->thread); |
1541 | spin_unlock(&fps->fcoe_rx_list.lock); | 1548 | spin_unlock(&fps->fcoe_rx_list.lock); |
1542 | 1549 | ||
1543 | return 0; | 1550 | return NET_RX_SUCCESS; |
1544 | err: | 1551 | err: |
1545 | per_cpu_ptr(lport->stats, get_cpu())->ErrorFrames++; | 1552 | per_cpu_ptr(lport->stats, get_cpu())->ErrorFrames++; |
1546 | put_cpu(); | 1553 | put_cpu(); |
1547 | err2: | 1554 | err2: |
1548 | kfree_skb(skb); | 1555 | kfree_skb(skb); |
1549 | return -1; | 1556 | return NET_RX_DROP; |
1550 | } | 1557 | } |
1551 | 1558 | ||
1552 | /** | 1559 | /** |
@@ -1788,13 +1795,13 @@ static void fcoe_recv_frame(struct sk_buff *skb) | |||
1788 | lport = fr->fr_dev; | 1795 | lport = fr->fr_dev; |
1789 | if (unlikely(!lport)) { | 1796 | if (unlikely(!lport)) { |
1790 | if (skb->destructor != fcoe_percpu_flush_done) | 1797 | if (skb->destructor != fcoe_percpu_flush_done) |
1791 | FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb"); | 1798 | FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb\n"); |
1792 | kfree_skb(skb); | 1799 | kfree_skb(skb); |
1793 | return; | 1800 | return; |
1794 | } | 1801 | } |
1795 | 1802 | ||
1796 | FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d " | 1803 | FCOE_NETDEV_DBG(skb->dev, |
1797 | "head:%p data:%p tail:%p end:%p sum:%d dev:%s", | 1804 | "skb_info: len:%d data_len:%d head:%p data:%p tail:%p end:%p sum:%d dev:%s\n", |
1798 | skb->len, skb->data_len, | 1805 | skb->len, skb->data_len, |
1799 | skb->head, skb->data, skb_tail_pointer(skb), | 1806 | skb->head, skb->data, skb_tail_pointer(skb), |
1800 | skb_end_pointer(skb), skb->csum, | 1807 | skb_end_pointer(skb), skb->csum, |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 203415e02518..34a1b1f333b4 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -160,74 +160,113 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) | |||
160 | } | 160 | } |
161 | EXPORT_SYMBOL(fcoe_ctlr_init); | 161 | EXPORT_SYMBOL(fcoe_ctlr_init); |
162 | 162 | ||
163 | /** | ||
164 | * fcoe_sysfs_fcf_add() - Add a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} | ||
165 | * @new: The newly discovered FCF | ||
166 | * | ||
167 | * Called with fip->ctlr_mutex held | ||
168 | */ | ||
163 | static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) | 169 | static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) |
164 | { | 170 | { |
165 | struct fcoe_ctlr *fip = new->fip; | 171 | struct fcoe_ctlr *fip = new->fip; |
166 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | 172 | struct fcoe_ctlr_device *ctlr_dev; |
167 | struct fcoe_fcf_device temp, *fcf_dev; | 173 | struct fcoe_fcf_device *temp, *fcf_dev; |
168 | int rc = 0; | 174 | int rc = -ENOMEM; |
169 | 175 | ||
170 | LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", | 176 | LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", |
171 | new->fabric_name, new->fcf_mac); | 177 | new->fabric_name, new->fcf_mac); |
172 | 178 | ||
173 | mutex_lock(&ctlr_dev->lock); | 179 | temp = kzalloc(sizeof(*temp), GFP_KERNEL); |
174 | 180 | if (!temp) | |
175 | temp.fabric_name = new->fabric_name; | ||
176 | temp.switch_name = new->switch_name; | ||
177 | temp.fc_map = new->fc_map; | ||
178 | temp.vfid = new->vfid; | ||
179 | memcpy(temp.mac, new->fcf_mac, ETH_ALEN); | ||
180 | temp.priority = new->pri; | ||
181 | temp.fka_period = new->fka_period; | ||
182 | temp.selected = 0; /* default to unselected */ | ||
183 | |||
184 | fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp); | ||
185 | if (unlikely(!fcf_dev)) { | ||
186 | rc = -ENOMEM; | ||
187 | goto out; | 181 | goto out; |
188 | } | 182 | |
183 | temp->fabric_name = new->fabric_name; | ||
184 | temp->switch_name = new->switch_name; | ||
185 | temp->fc_map = new->fc_map; | ||
186 | temp->vfid = new->vfid; | ||
187 | memcpy(temp->mac, new->fcf_mac, ETH_ALEN); | ||
188 | temp->priority = new->pri; | ||
189 | temp->fka_period = new->fka_period; | ||
190 | temp->selected = 0; /* default to unselected */ | ||
189 | 191 | ||
190 | /* | 192 | /* |
191 | * The fcoe_sysfs layer can return a CONNECTED fcf that | 193 | * If ctlr_dev doesn't exist then it means we're a libfcoe user |
192 | * has a priv (fcf was never deleted) or a CONNECTED fcf | 194 | * who doesn't use fcoe_syfs and didn't allocate a fcoe_ctlr_device. |
193 | * that doesn't have a priv (fcf was deleted). However, | 195 | * fnic would be an example of a driver with this behavior. In this |
194 | * libfcoe will always delete FCFs before trying to add | 196 | * case we want to add the fcoe_fcf to the fcoe_ctlr list, but we |
195 | * them. This is ensured because both recv_adv and | 197 | * don't want to make sysfs changes. |
196 | * age_fcfs are protected by the the fcoe_ctlr's mutex. | ||
197 | * This means that we should never get a FCF with a | ||
198 | * non-NULL priv pointer. | ||
199 | */ | 198 | */ |
200 | BUG_ON(fcf_dev->priv); | ||
201 | 199 | ||
202 | fcf_dev->priv = new; | 200 | ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); |
203 | new->fcf_dev = fcf_dev; | 201 | if (ctlr_dev) { |
202 | mutex_lock(&ctlr_dev->lock); | ||
203 | fcf_dev = fcoe_fcf_device_add(ctlr_dev, temp); | ||
204 | if (unlikely(!fcf_dev)) { | ||
205 | rc = -ENOMEM; | ||
206 | mutex_unlock(&ctlr_dev->lock); | ||
207 | goto out; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * The fcoe_sysfs layer can return a CONNECTED fcf that | ||
212 | * has a priv (fcf was never deleted) or a CONNECTED fcf | ||
213 | * that doesn't have a priv (fcf was deleted). However, | ||
214 | * libfcoe will always delete FCFs before trying to add | ||
215 | * them. This is ensured because both recv_adv and | ||
216 | * age_fcfs are protected by the the fcoe_ctlr's mutex. | ||
217 | * This means that we should never get a FCF with a | ||
218 | * non-NULL priv pointer. | ||
219 | */ | ||
220 | BUG_ON(fcf_dev->priv); | ||
221 | |||
222 | fcf_dev->priv = new; | ||
223 | new->fcf_dev = fcf_dev; | ||
224 | mutex_unlock(&ctlr_dev->lock); | ||
225 | } | ||
204 | 226 | ||
205 | list_add(&new->list, &fip->fcfs); | 227 | list_add(&new->list, &fip->fcfs); |
206 | fip->fcf_count++; | 228 | fip->fcf_count++; |
229 | rc = 0; | ||
207 | 230 | ||
208 | out: | 231 | out: |
209 | mutex_unlock(&ctlr_dev->lock); | 232 | kfree(temp); |
210 | return rc; | 233 | return rc; |
211 | } | 234 | } |
212 | 235 | ||
236 | /** | ||
237 | * fcoe_sysfs_fcf_del() - Remove a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} | ||
238 | * @new: The FCF to be removed | ||
239 | * | ||
240 | * Called with fip->ctlr_mutex held | ||
241 | */ | ||
213 | static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) | 242 | static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) |
214 | { | 243 | { |
215 | struct fcoe_ctlr *fip = new->fip; | 244 | struct fcoe_ctlr *fip = new->fip; |
216 | struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); | 245 | struct fcoe_ctlr_device *cdev; |
217 | struct fcoe_fcf_device *fcf_dev; | 246 | struct fcoe_fcf_device *fcf_dev; |
218 | 247 | ||
219 | list_del(&new->list); | 248 | list_del(&new->list); |
220 | fip->fcf_count--; | 249 | fip->fcf_count--; |
221 | 250 | ||
222 | mutex_lock(&ctlr_dev->lock); | 251 | /* |
223 | 252 | * If ctlr_dev doesn't exist then it means we're a libfcoe user | |
224 | fcf_dev = fcoe_fcf_to_fcf_dev(new); | 253 | * who doesn't use fcoe_syfs and didn't allocate a fcoe_ctlr_device |
225 | WARN_ON(!fcf_dev); | 254 | * or a fcoe_fcf_device. |
226 | new->fcf_dev = NULL; | 255 | * |
227 | fcoe_fcf_device_delete(fcf_dev); | 256 | * fnic would be an example of a driver with this behavior. In this |
228 | kfree(new); | 257 | * case we want to remove the fcoe_fcf from the fcoe_ctlr list (above), |
229 | 258 | * but we don't want to make sysfs changes. | |
230 | mutex_unlock(&ctlr_dev->lock); | 259 | */ |
260 | cdev = fcoe_ctlr_to_ctlr_dev(fip); | ||
261 | if (cdev) { | ||
262 | mutex_lock(&cdev->lock); | ||
263 | fcf_dev = fcoe_fcf_to_fcf_dev(new); | ||
264 | WARN_ON(!fcf_dev); | ||
265 | new->fcf_dev = NULL; | ||
266 | fcoe_fcf_device_delete(fcf_dev); | ||
267 | kfree(new); | ||
268 | mutex_unlock(&cdev->lock); | ||
269 | } | ||
231 | } | 270 | } |
232 | 271 | ||
233 | /** | 272 | /** |
@@ -300,7 +339,7 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) | |||
300 | spin_unlock_bh(&fip->ctlr_lock); | 339 | spin_unlock_bh(&fip->ctlr_lock); |
301 | sel = fip->sel_fcf; | 340 | sel = fip->sel_fcf; |
302 | 341 | ||
303 | if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) | 342 | if (sel && ether_addr_equal(sel->fcf_mac, fip->dest_addr)) |
304 | goto unlock; | 343 | goto unlock; |
305 | if (!is_zero_ether_addr(fip->dest_addr)) { | 344 | if (!is_zero_ether_addr(fip->dest_addr)) { |
306 | printk(KERN_NOTICE "libfcoe: host%d: " | 345 | printk(KERN_NOTICE "libfcoe: host%d: " |
@@ -1000,7 +1039,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
1000 | if (fcf->switch_name == new.switch_name && | 1039 | if (fcf->switch_name == new.switch_name && |
1001 | fcf->fabric_name == new.fabric_name && | 1040 | fcf->fabric_name == new.fabric_name && |
1002 | fcf->fc_map == new.fc_map && | 1041 | fcf->fc_map == new.fc_map && |
1003 | compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { | 1042 | ether_addr_equal(fcf->fcf_mac, new.fcf_mac)) { |
1004 | found = 1; | 1043 | found = 1; |
1005 | break; | 1044 | break; |
1006 | } | 1045 | } |
@@ -1340,7 +1379,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1340 | mp = (struct fip_mac_desc *)desc; | 1379 | mp = (struct fip_mac_desc *)desc; |
1341 | if (dlen < sizeof(*mp)) | 1380 | if (dlen < sizeof(*mp)) |
1342 | goto err; | 1381 | goto err; |
1343 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) | 1382 | if (!ether_addr_equal(mp->fd_mac, fcf->fcf_mac)) |
1344 | goto err; | 1383 | goto err; |
1345 | desc_mask &= ~BIT(FIP_DT_MAC); | 1384 | desc_mask &= ~BIT(FIP_DT_MAC); |
1346 | break; | 1385 | break; |
@@ -1418,8 +1457,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
1418 | * 'port_id' is already validated, check MAC address and | 1457 | * 'port_id' is already validated, check MAC address and |
1419 | * wwpn | 1458 | * wwpn |
1420 | */ | 1459 | */ |
1421 | if (compare_ether_addr(fip->get_src_addr(vn_port), | 1460 | if (!ether_addr_equal(fip->get_src_addr(vn_port), |
1422 | vp->fd_mac) != 0 || | 1461 | vp->fd_mac) || |
1423 | get_unaligned_be64(&vp->fd_wwpn) != | 1462 | get_unaligned_be64(&vp->fd_wwpn) != |
1424 | vn_port->wwpn) | 1463 | vn_port->wwpn) |
1425 | continue; | 1464 | continue; |
@@ -1453,6 +1492,9 @@ err: | |||
1453 | */ | 1492 | */ |
1454 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) | 1493 | void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) |
1455 | { | 1494 | { |
1495 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
1496 | if (!skb) | ||
1497 | return; | ||
1456 | skb_queue_tail(&fip->fip_recv_list, skb); | 1498 | skb_queue_tail(&fip->fip_recv_list, skb); |
1457 | schedule_work(&fip->recv_work); | 1499 | schedule_work(&fip->recv_work); |
1458 | } | 1500 | } |
@@ -1479,12 +1521,12 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
1479 | goto drop; | 1521 | goto drop; |
1480 | eh = eth_hdr(skb); | 1522 | eh = eth_hdr(skb); |
1481 | if (fip->mode == FIP_MODE_VN2VN) { | 1523 | if (fip->mode == FIP_MODE_VN2VN) { |
1482 | if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && | 1524 | if (!ether_addr_equal(eh->h_dest, fip->ctl_src_addr) && |
1483 | compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) && | 1525 | !ether_addr_equal(eh->h_dest, fcoe_all_vn2vn) && |
1484 | compare_ether_addr(eh->h_dest, fcoe_all_p2p)) | 1526 | !ether_addr_equal(eh->h_dest, fcoe_all_p2p)) |
1485 | goto drop; | 1527 | goto drop; |
1486 | } else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && | 1528 | } else if (!ether_addr_equal(eh->h_dest, fip->ctl_src_addr) && |
1487 | compare_ether_addr(eh->h_dest, fcoe_all_enode)) | 1529 | !ether_addr_equal(eh->h_dest, fcoe_all_enode)) |
1488 | goto drop; | 1530 | goto drop; |
1489 | fiph = (struct fip_header *)skb->data; | 1531 | fiph = (struct fip_header *)skb->data; |
1490 | op = ntohs(fiph->fip_op); | 1532 | op = ntohs(fiph->fip_op); |
@@ -1856,7 +1898,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
1856 | * address_mode flag to use FC_OUI-based Ethernet DA. | 1898 | * address_mode flag to use FC_OUI-based Ethernet DA. |
1857 | * Otherwise we use the FCoE gateway addr | 1899 | * Otherwise we use the FCoE gateway addr |
1858 | */ | 1900 | */ |
1859 | if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { | 1901 | if (ether_addr_equal(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { |
1860 | fcoe_ctlr_map_dest(fip); | 1902 | fcoe_ctlr_map_dest(fip); |
1861 | } else { | 1903 | } else { |
1862 | memcpy(fip->dest_addr, sa, ETH_ALEN); | 1904 | memcpy(fip->dest_addr, sa, ETH_ALEN); |
@@ -2825,8 +2867,8 @@ unlock: | |||
2825 | * disabled, so that should ensure that this routine is only called | 2867 | * disabled, so that should ensure that this routine is only called |
2826 | * when nothing is happening. | 2868 | * when nothing is happening. |
2827 | */ | 2869 | */ |
2828 | void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip, | 2870 | static void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip, |
2829 | enum fip_state fip_mode) | 2871 | enum fip_state fip_mode) |
2830 | { | 2872 | { |
2831 | void *priv; | 2873 | void *priv; |
2832 | 2874 | ||
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index 1f4f22fe8281..045c4e11ee54 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c | |||
@@ -300,29 +300,29 @@ static ssize_t store_ctlr_mode(struct device *dev, | |||
300 | 300 | ||
301 | switch (ctlr->enabled) { | 301 | switch (ctlr->enabled) { |
302 | case FCOE_CTLR_ENABLED: | 302 | case FCOE_CTLR_ENABLED: |
303 | LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled."); | 303 | LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled.\n"); |
304 | return -EBUSY; | 304 | return -EBUSY; |
305 | case FCOE_CTLR_DISABLED: | 305 | case FCOE_CTLR_DISABLED: |
306 | if (!ctlr->f->set_fcoe_ctlr_mode) { | 306 | if (!ctlr->f->set_fcoe_ctlr_mode) { |
307 | LIBFCOE_SYSFS_DBG(ctlr, | 307 | LIBFCOE_SYSFS_DBG(ctlr, |
308 | "Mode change not supported by LLD."); | 308 | "Mode change not supported by LLD.\n"); |
309 | return -ENOTSUPP; | 309 | return -ENOTSUPP; |
310 | } | 310 | } |
311 | 311 | ||
312 | ctlr->mode = fcoe_parse_mode(mode); | 312 | ctlr->mode = fcoe_parse_mode(mode); |
313 | if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) { | 313 | if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) { |
314 | LIBFCOE_SYSFS_DBG(ctlr, | 314 | LIBFCOE_SYSFS_DBG(ctlr, "Unknown mode %s provided.\n", |
315 | "Unknown mode %s provided.", buf); | 315 | buf); |
316 | return -EINVAL; | 316 | return -EINVAL; |
317 | } | 317 | } |
318 | 318 | ||
319 | ctlr->f->set_fcoe_ctlr_mode(ctlr); | 319 | ctlr->f->set_fcoe_ctlr_mode(ctlr); |
320 | LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.", buf); | 320 | LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.\n", buf); |
321 | 321 | ||
322 | return count; | 322 | return count; |
323 | case FCOE_CTLR_UNUSED: | 323 | case FCOE_CTLR_UNUSED: |
324 | default: | 324 | default: |
325 | LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported."); | 325 | LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.\n"); |
326 | return -ENOTSUPP; | 326 | return -ENOTSUPP; |
327 | }; | 327 | }; |
328 | } | 328 | } |
@@ -657,7 +657,7 @@ static int fcoe_fcf_device_match(struct fcoe_fcf_device *new, | |||
657 | if (new->switch_name == old->switch_name && | 657 | if (new->switch_name == old->switch_name && |
658 | new->fabric_name == old->fabric_name && | 658 | new->fabric_name == old->fabric_name && |
659 | new->fc_map == old->fc_map && | 659 | new->fc_map == old->fc_map && |
660 | compare_ether_addr(new->mac, old->mac) == 0) | 660 | ether_addr_equal(new->mac, old->mac)) |
661 | return 1; | 661 | return 1; |
662 | return 0; | 662 | return 0; |
663 | } | 663 | } |
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index e4dd3d7cd236..528d43b7b569 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "fnic_io.h" | 27 | #include "fnic_io.h" |
28 | #include "fnic_res.h" | 28 | #include "fnic_res.h" |
29 | #include "fnic_trace.h" | 29 | #include "fnic_trace.h" |
30 | #include "fnic_stats.h" | ||
30 | #include "vnic_dev.h" | 31 | #include "vnic_dev.h" |
31 | #include "vnic_wq.h" | 32 | #include "vnic_wq.h" |
32 | #include "vnic_rq.h" | 33 | #include "vnic_rq.h" |
@@ -38,7 +39,7 @@ | |||
38 | 39 | ||
39 | #define DRV_NAME "fnic" | 40 | #define DRV_NAME "fnic" |
40 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 41 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
41 | #define DRV_VERSION "1.5.0.23" | 42 | #define DRV_VERSION "1.5.0.45" |
42 | #define PFX DRV_NAME ": " | 43 | #define PFX DRV_NAME ": " |
43 | #define DFX DRV_NAME "%d: " | 44 | #define DFX DRV_NAME "%d: " |
44 | 45 | ||
@@ -232,6 +233,13 @@ struct fnic { | |||
232 | unsigned int wq_count; | 233 | unsigned int wq_count; |
233 | unsigned int cq_count; | 234 | unsigned int cq_count; |
234 | 235 | ||
236 | struct dentry *fnic_stats_debugfs_host; | ||
237 | struct dentry *fnic_stats_debugfs_file; | ||
238 | struct dentry *fnic_reset_debugfs_file; | ||
239 | unsigned int reset_stats; | ||
240 | atomic64_t io_cmpl_skip; | ||
241 | struct fnic_stats fnic_stats; | ||
242 | |||
235 | u32 vlan_hw_insert:1; /* let hw insert the tag */ | 243 | u32 vlan_hw_insert:1; /* let hw insert the tag */ |
236 | u32 in_remove:1; /* fnic device in removal */ | 244 | u32 in_remove:1; /* fnic device in removal */ |
237 | u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */ | 245 | u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */ |
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c index cbcb0121c84d..b6073f875761 100644 --- a/drivers/scsi/fnic/fnic_debugfs.c +++ b/drivers/scsi/fnic/fnic_debugfs.c | |||
@@ -23,6 +23,58 @@ | |||
23 | static struct dentry *fnic_trace_debugfs_root; | 23 | static struct dentry *fnic_trace_debugfs_root; |
24 | static struct dentry *fnic_trace_debugfs_file; | 24 | static struct dentry *fnic_trace_debugfs_file; |
25 | static struct dentry *fnic_trace_enable; | 25 | static struct dentry *fnic_trace_enable; |
26 | static struct dentry *fnic_stats_debugfs_root; | ||
27 | |||
28 | /* | ||
29 | * fnic_debugfs_init - Initialize debugfs for fnic debug logging | ||
30 | * | ||
31 | * Description: | ||
32 | * When Debugfs is configured this routine sets up the fnic debugfs | ||
33 | * file system. If not already created, this routine will create the | ||
34 | * fnic directory and statistics directory for trace buffer and | ||
35 | * stats logging. | ||
36 | */ | ||
37 | int fnic_debugfs_init(void) | ||
38 | { | ||
39 | int rc = -1; | ||
40 | fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL); | ||
41 | if (!fnic_trace_debugfs_root) { | ||
42 | printk(KERN_DEBUG "Cannot create debugfs root\n"); | ||
43 | return rc; | ||
44 | } | ||
45 | |||
46 | if (!fnic_trace_debugfs_root) { | ||
47 | printk(KERN_DEBUG | ||
48 | "fnic root directory doesn't exist in debugfs\n"); | ||
49 | return rc; | ||
50 | } | ||
51 | |||
52 | fnic_stats_debugfs_root = debugfs_create_dir("statistics", | ||
53 | fnic_trace_debugfs_root); | ||
54 | if (!fnic_stats_debugfs_root) { | ||
55 | printk(KERN_DEBUG "Cannot create Statistics directory\n"); | ||
56 | return rc; | ||
57 | } | ||
58 | |||
59 | rc = 0; | ||
60 | return rc; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * fnic_debugfs_terminate - Tear down debugfs infrastructure | ||
65 | * | ||
66 | * Description: | ||
67 | * When Debugfs is configured this routine removes debugfs file system | ||
68 | * elements that are specific to fnic. | ||
69 | */ | ||
70 | void fnic_debugfs_terminate(void) | ||
71 | { | ||
72 | debugfs_remove(fnic_stats_debugfs_root); | ||
73 | fnic_stats_debugfs_root = NULL; | ||
74 | |||
75 | debugfs_remove(fnic_trace_debugfs_root); | ||
76 | fnic_trace_debugfs_root = NULL; | ||
77 | } | ||
26 | 78 | ||
27 | /* | 79 | /* |
28 | * fnic_trace_ctrl_open - Open the trace_enable file | 80 | * fnic_trace_ctrl_open - Open the trace_enable file |
@@ -241,16 +293,16 @@ static const struct file_operations fnic_trace_debugfs_fops = { | |||
241 | * Description: | 293 | * Description: |
242 | * When Debugfs is configured this routine sets up the fnic debugfs | 294 | * When Debugfs is configured this routine sets up the fnic debugfs |
243 | * file system. If not already created, this routine will create the | 295 | * file system. If not already created, this routine will create the |
244 | * fnic directory. It will create file trace to log fnic trace buffer | 296 | * create file trace to log fnic trace buffer output into debugfs and |
245 | * output into debugfs and it will also create file trace_enable to | 297 | * it will also create file trace_enable to control enable/disable of |
246 | * control enable/disable of trace logging into trace buffer. | 298 | * trace logging into trace buffer. |
247 | */ | 299 | */ |
248 | int fnic_trace_debugfs_init(void) | 300 | int fnic_trace_debugfs_init(void) |
249 | { | 301 | { |
250 | int rc = -1; | 302 | int rc = -1; |
251 | fnic_trace_debugfs_root = debugfs_create_dir("fnic", NULL); | ||
252 | if (!fnic_trace_debugfs_root) { | 303 | if (!fnic_trace_debugfs_root) { |
253 | printk(KERN_DEBUG "Cannot create debugfs root\n"); | 304 | printk(KERN_DEBUG |
305 | "FNIC Debugfs root directory doesn't exist\n"); | ||
254 | return rc; | 306 | return rc; |
255 | } | 307 | } |
256 | fnic_trace_enable = debugfs_create_file("tracing_enable", | 308 | fnic_trace_enable = debugfs_create_file("tracing_enable", |
@@ -259,8 +311,8 @@ int fnic_trace_debugfs_init(void) | |||
259 | NULL, &fnic_trace_ctrl_fops); | 311 | NULL, &fnic_trace_ctrl_fops); |
260 | 312 | ||
261 | if (!fnic_trace_enable) { | 313 | if (!fnic_trace_enable) { |
262 | printk(KERN_DEBUG "Cannot create trace_enable file" | 314 | printk(KERN_DEBUG |
263 | " under debugfs"); | 315 | "Cannot create trace_enable file under debugfs\n"); |
264 | return rc; | 316 | return rc; |
265 | } | 317 | } |
266 | 318 | ||
@@ -271,7 +323,8 @@ int fnic_trace_debugfs_init(void) | |||
271 | &fnic_trace_debugfs_fops); | 323 | &fnic_trace_debugfs_fops); |
272 | 324 | ||
273 | if (!fnic_trace_debugfs_file) { | 325 | if (!fnic_trace_debugfs_file) { |
274 | printk(KERN_DEBUG "Cannot create trace file under debugfs"); | 326 | printk(KERN_DEBUG |
327 | "Cannot create trace file under debugfs\n"); | ||
275 | return rc; | 328 | return rc; |
276 | } | 329 | } |
277 | rc = 0; | 330 | rc = 0; |
@@ -295,8 +348,323 @@ void fnic_trace_debugfs_terminate(void) | |||
295 | debugfs_remove(fnic_trace_enable); | 348 | debugfs_remove(fnic_trace_enable); |
296 | fnic_trace_enable = NULL; | 349 | fnic_trace_enable = NULL; |
297 | } | 350 | } |
298 | if (fnic_trace_debugfs_root) { | 351 | } |
299 | debugfs_remove(fnic_trace_debugfs_root); | 352 | |
300 | fnic_trace_debugfs_root = NULL; | 353 | /* |
354 | * fnic_reset_stats_open - Open the reset_stats file | ||
355 | * @inode: The inode pointer. | ||
356 | * @file: The file pointer to attach the stats reset flag. | ||
357 | * | ||
358 | * Description: | ||
359 | * This routine opens a debugsfs file reset_stats and stores i_private data | ||
360 | * to debug structure to retrieve later for while performing other | ||
361 | * file oprations. | ||
362 | * | ||
363 | * Returns: | ||
364 | * This function returns zero if successful. | ||
365 | */ | ||
366 | static int fnic_reset_stats_open(struct inode *inode, struct file *file) | ||
367 | { | ||
368 | struct stats_debug_info *debug; | ||
369 | |||
370 | debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL); | ||
371 | if (!debug) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | debug->i_private = inode->i_private; | ||
375 | |||
376 | file->private_data = debug; | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * fnic_reset_stats_read - Read a reset_stats debugfs file | ||
383 | * @filp: The file pointer to read from. | ||
384 | * @ubuf: The buffer to copy the data to. | ||
385 | * @cnt: The number of bytes to read. | ||
386 | * @ppos: The position in the file to start reading from. | ||
387 | * | ||
388 | * Description: | ||
389 | * This routine reads value of variable reset_stats | ||
390 | * and stores into local @buf. It will start reading file at @ppos and | ||
391 | * copy up to @cnt of data to @ubuf from @buf. | ||
392 | * | ||
393 | * Returns: | ||
394 | * This function returns the amount of data that was read. | ||
395 | */ | ||
396 | static ssize_t fnic_reset_stats_read(struct file *file, | ||
397 | char __user *ubuf, | ||
398 | size_t cnt, loff_t *ppos) | ||
399 | { | ||
400 | struct stats_debug_info *debug = file->private_data; | ||
401 | struct fnic *fnic = (struct fnic *)debug->i_private; | ||
402 | char buf[64]; | ||
403 | int len; | ||
404 | |||
405 | len = sprintf(buf, "%u\n", fnic->reset_stats); | ||
406 | |||
407 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); | ||
408 | } | ||
409 | |||
410 | /* | ||
411 | * fnic_reset_stats_write - Write to reset_stats debugfs file | ||
412 | * @filp: The file pointer to write from. | ||
413 | * @ubuf: The buffer to copy the data from. | ||
414 | * @cnt: The number of bytes to write. | ||
415 | * @ppos: The position in the file to start writing to. | ||
416 | * | ||
417 | * Description: | ||
418 | * This routine writes data from user buffer @ubuf to buffer @buf and | ||
419 | * resets cumulative stats of fnic. | ||
420 | * | ||
421 | * Returns: | ||
422 | * This function returns the amount of data that was written. | ||
423 | */ | ||
424 | static ssize_t fnic_reset_stats_write(struct file *file, | ||
425 | const char __user *ubuf, | ||
426 | size_t cnt, loff_t *ppos) | ||
427 | { | ||
428 | struct stats_debug_info *debug = file->private_data; | ||
429 | struct fnic *fnic = (struct fnic *)debug->i_private; | ||
430 | struct fnic_stats *stats = &fnic->fnic_stats; | ||
431 | u64 *io_stats_p = (u64 *)&stats->io_stats; | ||
432 | u64 *fw_stats_p = (u64 *)&stats->fw_stats; | ||
433 | char buf[64]; | ||
434 | unsigned long val; | ||
435 | int ret; | ||
436 | |||
437 | if (cnt >= sizeof(buf)) | ||
438 | return -EINVAL; | ||
439 | |||
440 | if (copy_from_user(&buf, ubuf, cnt)) | ||
441 | return -EFAULT; | ||
442 | |||
443 | buf[cnt] = 0; | ||
444 | |||
445 | ret = kstrtoul(buf, 10, &val); | ||
446 | if (ret < 0) | ||
447 | return ret; | ||
448 | |||
449 | fnic->reset_stats = val; | ||
450 | |||
451 | if (fnic->reset_stats) { | ||
452 | /* Skip variable is used to avoid descrepancies to Num IOs | ||
453 | * and IO Completions stats. Skip incrementing No IO Compls | ||
454 | * for pending active IOs after reset stats | ||
455 | */ | ||
456 | atomic64_set(&fnic->io_cmpl_skip, | ||
457 | atomic64_read(&stats->io_stats.active_ios)); | ||
458 | memset(&stats->abts_stats, 0, sizeof(struct abort_stats)); | ||
459 | memset(&stats->term_stats, 0, | ||
460 | sizeof(struct terminate_stats)); | ||
461 | memset(&stats->reset_stats, 0, sizeof(struct reset_stats)); | ||
462 | memset(&stats->misc_stats, 0, sizeof(struct misc_stats)); | ||
463 | memset(&stats->vlan_stats, 0, sizeof(struct vlan_stats)); | ||
464 | memset(io_stats_p+1, 0, | ||
465 | sizeof(struct io_path_stats) - sizeof(u64)); | ||
466 | memset(fw_stats_p+1, 0, | ||
467 | sizeof(struct fw_stats) - sizeof(u64)); | ||
301 | } | 468 | } |
469 | |||
470 | (*ppos)++; | ||
471 | return cnt; | ||
472 | } | ||
473 | |||
474 | /* | ||
475 | * fnic_reset_stats_release - Release the buffer used to store | ||
476 | * debugfs file data | ||
477 | * @inode: The inode pointer | ||
478 | * @file: The file pointer that contains the buffer to release | ||
479 | * | ||
480 | * Description: | ||
481 | * This routine frees the buffer that was allocated when the debugfs | ||
482 | * file was opened. | ||
483 | * | ||
484 | * Returns: | ||
485 | * This function returns zero. | ||
486 | */ | ||
487 | static int fnic_reset_stats_release(struct inode *inode, | ||
488 | struct file *file) | ||
489 | { | ||
490 | struct stats_debug_info *debug = file->private_data; | ||
491 | kfree(debug); | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /* | ||
496 | * fnic_stats_debugfs_open - Open the stats file for specific host | ||
497 | * and get fnic stats. | ||
498 | * @inode: The inode pointer. | ||
499 | * @file: The file pointer to attach the specific host statistics. | ||
500 | * | ||
501 | * Description: | ||
502 | * This routine opens a debugsfs file stats of specific host and print | ||
503 | * fnic stats. | ||
504 | * | ||
505 | * Returns: | ||
506 | * This function returns zero if successful. | ||
507 | */ | ||
508 | static int fnic_stats_debugfs_open(struct inode *inode, | ||
509 | struct file *file) | ||
510 | { | ||
511 | struct fnic *fnic = inode->i_private; | ||
512 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
513 | struct stats_debug_info *debug; | ||
514 | int buf_size = 2 * PAGE_SIZE; | ||
515 | |||
516 | debug = kzalloc(sizeof(struct stats_debug_info), GFP_KERNEL); | ||
517 | if (!debug) | ||
518 | return -ENOMEM; | ||
519 | |||
520 | debug->debug_buffer = vmalloc(buf_size); | ||
521 | if (!debug->debug_buffer) { | ||
522 | kfree(debug); | ||
523 | return -ENOMEM; | ||
524 | } | ||
525 | |||
526 | debug->buf_size = buf_size; | ||
527 | memset((void *)debug->debug_buffer, 0, buf_size); | ||
528 | debug->buffer_len = fnic_get_stats_data(debug, fnic_stats); | ||
529 | |||
530 | file->private_data = debug; | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * fnic_stats_debugfs_read - Read a debugfs file | ||
537 | * @file: The file pointer to read from. | ||
538 | * @ubuf: The buffer to copy the data to. | ||
539 | * @nbytes: The number of bytes to read. | ||
540 | * @pos: The position in the file to start reading from. | ||
541 | * | ||
542 | * Description: | ||
543 | * This routine reads data from the buffer indicated in the private_data | ||
544 | * field of @file. It will start reading at @pos and copy up to @nbytes of | ||
545 | * data to @ubuf. | ||
546 | * | ||
547 | * Returns: | ||
548 | * This function returns the amount of data that was read (this could be | ||
549 | * less than @nbytes if the end of the file was reached). | ||
550 | */ | ||
551 | static ssize_t fnic_stats_debugfs_read(struct file *file, | ||
552 | char __user *ubuf, | ||
553 | size_t nbytes, | ||
554 | loff_t *pos) | ||
555 | { | ||
556 | struct stats_debug_info *debug = file->private_data; | ||
557 | int rc = 0; | ||
558 | rc = simple_read_from_buffer(ubuf, nbytes, pos, | ||
559 | debug->debug_buffer, | ||
560 | debug->buffer_len); | ||
561 | return rc; | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * fnic_stats_stats_release - Release the buffer used to store | ||
566 | * debugfs file data | ||
567 | * @inode: The inode pointer | ||
568 | * @file: The file pointer that contains the buffer to release | ||
569 | * | ||
570 | * Description: | ||
571 | * This routine frees the buffer that was allocated when the debugfs | ||
572 | * file was opened. | ||
573 | * | ||
574 | * Returns: | ||
575 | * This function returns zero. | ||
576 | */ | ||
577 | static int fnic_stats_debugfs_release(struct inode *inode, | ||
578 | struct file *file) | ||
579 | { | ||
580 | struct stats_debug_info *debug = file->private_data; | ||
581 | vfree(debug->debug_buffer); | ||
582 | kfree(debug); | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static const struct file_operations fnic_stats_debugfs_fops = { | ||
587 | .owner = THIS_MODULE, | ||
588 | .open = fnic_stats_debugfs_open, | ||
589 | .read = fnic_stats_debugfs_read, | ||
590 | .release = fnic_stats_debugfs_release, | ||
591 | }; | ||
592 | |||
593 | static const struct file_operations fnic_reset_debugfs_fops = { | ||
594 | .owner = THIS_MODULE, | ||
595 | .open = fnic_reset_stats_open, | ||
596 | .read = fnic_reset_stats_read, | ||
597 | .write = fnic_reset_stats_write, | ||
598 | .release = fnic_reset_stats_release, | ||
599 | }; | ||
600 | |||
601 | /* | ||
602 | * fnic_stats_init - Initialize stats struct and create stats file per fnic | ||
603 | * | ||
604 | * Description: | ||
605 | * When Debugfs is configured this routine sets up the stats file per fnic | ||
606 | * It will create file stats and reset_stats under statistics/host# directory | ||
607 | * to log per fnic stats. | ||
608 | */ | ||
609 | int fnic_stats_debugfs_init(struct fnic *fnic) | ||
610 | { | ||
611 | int rc = -1; | ||
612 | char name[16]; | ||
613 | |||
614 | snprintf(name, sizeof(name), "host%d", fnic->lport->host->host_no); | ||
615 | |||
616 | if (!fnic_stats_debugfs_root) { | ||
617 | printk(KERN_DEBUG "fnic_stats root doesn't exist\n"); | ||
618 | return rc; | ||
619 | } | ||
620 | fnic->fnic_stats_debugfs_host = debugfs_create_dir(name, | ||
621 | fnic_stats_debugfs_root); | ||
622 | if (!fnic->fnic_stats_debugfs_host) { | ||
623 | printk(KERN_DEBUG "Cannot create host directory\n"); | ||
624 | return rc; | ||
625 | } | ||
626 | |||
627 | fnic->fnic_stats_debugfs_file = debugfs_create_file("stats", | ||
628 | S_IFREG|S_IRUGO|S_IWUSR, | ||
629 | fnic->fnic_stats_debugfs_host, | ||
630 | fnic, | ||
631 | &fnic_stats_debugfs_fops); | ||
632 | if (!fnic->fnic_stats_debugfs_file) { | ||
633 | printk(KERN_DEBUG "Cannot create host stats file\n"); | ||
634 | return rc; | ||
635 | } | ||
636 | |||
637 | fnic->fnic_reset_debugfs_file = debugfs_create_file("reset_stats", | ||
638 | S_IFREG|S_IRUGO|S_IWUSR, | ||
639 | fnic->fnic_stats_debugfs_host, | ||
640 | fnic, | ||
641 | &fnic_reset_debugfs_fops); | ||
642 | if (!fnic->fnic_reset_debugfs_file) { | ||
643 | printk(KERN_DEBUG "Cannot create host stats file\n"); | ||
644 | return rc; | ||
645 | } | ||
646 | rc = 0; | ||
647 | return rc; | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * fnic_stats_debugfs_remove - Tear down debugfs infrastructure of stats | ||
652 | * | ||
653 | * Description: | ||
654 | * When Debugfs is configured this routine removes debugfs file system | ||
655 | * elements that are specific to fnic stats. | ||
656 | */ | ||
657 | void fnic_stats_debugfs_remove(struct fnic *fnic) | ||
658 | { | ||
659 | if (!fnic) | ||
660 | return; | ||
661 | |||
662 | debugfs_remove(fnic->fnic_stats_debugfs_file); | ||
663 | fnic->fnic_stats_debugfs_file = NULL; | ||
664 | |||
665 | debugfs_remove(fnic->fnic_reset_debugfs_file); | ||
666 | fnic->fnic_reset_debugfs_file = NULL; | ||
667 | |||
668 | debugfs_remove(fnic->fnic_stats_debugfs_host); | ||
669 | fnic->fnic_stats_debugfs_host = NULL; | ||
302 | } | 670 | } |
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 006fa92a02df..1671325aec7f 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c | |||
@@ -302,6 +302,7 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip, | |||
302 | static void fnic_fcoe_send_vlan_req(struct fnic *fnic) | 302 | static void fnic_fcoe_send_vlan_req(struct fnic *fnic) |
303 | { | 303 | { |
304 | struct fcoe_ctlr *fip = &fnic->ctlr; | 304 | struct fcoe_ctlr *fip = &fnic->ctlr; |
305 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
305 | struct sk_buff *skb; | 306 | struct sk_buff *skb; |
306 | char *eth_fr; | 307 | char *eth_fr; |
307 | int fr_len; | 308 | int fr_len; |
@@ -337,6 +338,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic) | |||
337 | vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME; | 338 | vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME; |
338 | vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW; | 339 | vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW; |
339 | put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn); | 340 | put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn); |
341 | atomic64_inc(&fnic_stats->vlan_stats.vlan_disc_reqs); | ||
340 | 342 | ||
341 | skb_put(skb, sizeof(*vlan)); | 343 | skb_put(skb, sizeof(*vlan)); |
342 | skb->protocol = htons(ETH_P_FIP); | 344 | skb->protocol = htons(ETH_P_FIP); |
@@ -354,6 +356,7 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb) | |||
354 | struct fcoe_ctlr *fip = &fnic->ctlr; | 356 | struct fcoe_ctlr *fip = &fnic->ctlr; |
355 | struct fip_header *fiph; | 357 | struct fip_header *fiph; |
356 | struct fip_desc *desc; | 358 | struct fip_desc *desc; |
359 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
357 | u16 vid; | 360 | u16 vid; |
358 | size_t rlen; | 361 | size_t rlen; |
359 | size_t dlen; | 362 | size_t dlen; |
@@ -402,6 +405,7 @@ static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb) | |||
402 | /* any VLAN descriptors present ? */ | 405 | /* any VLAN descriptors present ? */ |
403 | if (list_empty(&fnic->vlans)) { | 406 | if (list_empty(&fnic->vlans)) { |
404 | /* retry from timer */ | 407 | /* retry from timer */ |
408 | atomic64_inc(&fnic_stats->vlan_stats.resp_withno_vlanID); | ||
405 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, | 409 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, |
406 | "No VLAN descriptors in FIP VLAN response\n"); | 410 | "No VLAN descriptors in FIP VLAN response\n"); |
407 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | 411 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); |
@@ -533,6 +537,7 @@ drop: | |||
533 | void fnic_handle_fip_frame(struct work_struct *work) | 537 | void fnic_handle_fip_frame(struct work_struct *work) |
534 | { | 538 | { |
535 | struct fnic *fnic = container_of(work, struct fnic, fip_frame_work); | 539 | struct fnic *fnic = container_of(work, struct fnic, fip_frame_work); |
540 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
536 | unsigned long flags; | 541 | unsigned long flags; |
537 | struct sk_buff *skb; | 542 | struct sk_buff *skb; |
538 | struct ethhdr *eh; | 543 | struct ethhdr *eh; |
@@ -567,6 +572,8 @@ void fnic_handle_fip_frame(struct work_struct *work) | |||
567 | * fcf's & restart from scratch | 572 | * fcf's & restart from scratch |
568 | */ | 573 | */ |
569 | if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) { | 574 | if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) { |
575 | atomic64_inc( | ||
576 | &fnic_stats->vlan_stats.flogi_rejects); | ||
570 | shost_printk(KERN_INFO, fnic->lport->host, | 577 | shost_printk(KERN_INFO, fnic->lport->host, |
571 | "Trigger a Link down - VLAN Disc\n"); | 578 | "Trigger a Link down - VLAN Disc\n"); |
572 | fcoe_ctlr_link_down(&fnic->ctlr); | 579 | fcoe_ctlr_link_down(&fnic->ctlr); |
@@ -651,13 +658,13 @@ void fnic_update_mac_locked(struct fnic *fnic, u8 *new) | |||
651 | 658 | ||
652 | if (is_zero_ether_addr(new)) | 659 | if (is_zero_ether_addr(new)) |
653 | new = ctl; | 660 | new = ctl; |
654 | if (!compare_ether_addr(data, new)) | 661 | if (ether_addr_equal(data, new)) |
655 | return; | 662 | return; |
656 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "update_mac %pM\n", new); | 663 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "update_mac %pM\n", new); |
657 | if (!is_zero_ether_addr(data) && compare_ether_addr(data, ctl)) | 664 | if (!is_zero_ether_addr(data) && !ether_addr_equal(data, ctl)) |
658 | vnic_dev_del_addr(fnic->vdev, data); | 665 | vnic_dev_del_addr(fnic->vdev, data); |
659 | memcpy(data, new, ETH_ALEN); | 666 | memcpy(data, new, ETH_ALEN); |
660 | if (compare_ether_addr(new, ctl)) | 667 | if (!ether_addr_equal(new, ctl)) |
661 | vnic_dev_add_addr(fnic->vdev, new); | 668 | vnic_dev_add_addr(fnic->vdev, new); |
662 | } | 669 | } |
663 | 670 | ||
@@ -753,6 +760,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
753 | struct fnic *fnic = vnic_dev_priv(rq->vdev); | 760 | struct fnic *fnic = vnic_dev_priv(rq->vdev); |
754 | struct sk_buff *skb; | 761 | struct sk_buff *skb; |
755 | struct fc_frame *fp; | 762 | struct fc_frame *fp; |
763 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
756 | unsigned int eth_hdrs_stripped; | 764 | unsigned int eth_hdrs_stripped; |
757 | u8 type, color, eop, sop, ingress_port, vlan_stripped; | 765 | u8 type, color, eop, sop, ingress_port, vlan_stripped; |
758 | u8 fcoe = 0, fcoe_sof, fcoe_eof; | 766 | u8 fcoe = 0, fcoe_sof, fcoe_eof; |
@@ -803,6 +811,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
803 | eth_hdrs_stripped = 0; | 811 | eth_hdrs_stripped = 0; |
804 | skb_trim(skb, bytes_written); | 812 | skb_trim(skb, bytes_written); |
805 | if (!fcs_ok) { | 813 | if (!fcs_ok) { |
814 | atomic64_inc(&fnic_stats->misc_stats.frame_errors); | ||
806 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 815 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
807 | "fcs error. dropping packet.\n"); | 816 | "fcs error. dropping packet.\n"); |
808 | goto drop; | 817 | goto drop; |
@@ -818,6 +827,7 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc | |||
818 | } | 827 | } |
819 | 828 | ||
820 | if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) { | 829 | if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) { |
830 | atomic64_inc(&fnic_stats->misc_stats.frame_errors); | ||
821 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 831 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
822 | "fnic rq_cmpl fcoe x%x fcsok x%x" | 832 | "fnic rq_cmpl fcoe x%x fcsok x%x" |
823 | " pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err" | 833 | " pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err" |
@@ -1205,6 +1215,7 @@ void fnic_handle_fip_timer(struct fnic *fnic) | |||
1205 | { | 1215 | { |
1206 | unsigned long flags; | 1216 | unsigned long flags; |
1207 | struct fcoe_vlan *vlan; | 1217 | struct fcoe_vlan *vlan; |
1218 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
1208 | u64 sol_time; | 1219 | u64 sol_time; |
1209 | 1220 | ||
1210 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 1221 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
@@ -1273,6 +1284,7 @@ void fnic_handle_fip_timer(struct fnic *fnic) | |||
1273 | vlan->state = FIP_VLAN_SENT; /* sent now */ | 1284 | vlan->state = FIP_VLAN_SENT; /* sent now */ |
1274 | } | 1285 | } |
1275 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | 1286 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); |
1287 | atomic64_inc(&fnic_stats->vlan_stats.sol_expiry_count); | ||
1276 | vlan->sol_count++; | 1288 | vlan->sol_count++; |
1277 | sol_time = jiffies + msecs_to_jiffies | 1289 | sol_time = jiffies + msecs_to_jiffies |
1278 | (FCOE_CTLR_START_DELAY); | 1290 | (FCOE_CTLR_START_DELAY); |
diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c index 5c1f223cabce..7d9b54ae7f62 100644 --- a/drivers/scsi/fnic/fnic_isr.c +++ b/drivers/scsi/fnic/fnic_isr.c | |||
@@ -37,6 +37,9 @@ static irqreturn_t fnic_isr_legacy(int irq, void *data) | |||
37 | if (!pba) | 37 | if (!pba) |
38 | return IRQ_NONE; | 38 | return IRQ_NONE; |
39 | 39 | ||
40 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
41 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
42 | |||
40 | if (pba & (1 << FNIC_INTX_NOTIFY)) { | 43 | if (pba & (1 << FNIC_INTX_NOTIFY)) { |
41 | vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_NOTIFY]); | 44 | vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_NOTIFY]); |
42 | fnic_handle_link_event(fnic); | 45 | fnic_handle_link_event(fnic); |
@@ -66,6 +69,9 @@ static irqreturn_t fnic_isr_msi(int irq, void *data) | |||
66 | struct fnic *fnic = data; | 69 | struct fnic *fnic = data; |
67 | unsigned long work_done = 0; | 70 | unsigned long work_done = 0; |
68 | 71 | ||
72 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
73 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
74 | |||
69 | work_done += fnic_wq_copy_cmpl_handler(fnic, -1); | 75 | work_done += fnic_wq_copy_cmpl_handler(fnic, -1); |
70 | work_done += fnic_wq_cmpl_handler(fnic, -1); | 76 | work_done += fnic_wq_cmpl_handler(fnic, -1); |
71 | work_done += fnic_rq_cmpl_handler(fnic, -1); | 77 | work_done += fnic_rq_cmpl_handler(fnic, -1); |
@@ -83,6 +89,9 @@ static irqreturn_t fnic_isr_msix_rq(int irq, void *data) | |||
83 | struct fnic *fnic = data; | 89 | struct fnic *fnic = data; |
84 | unsigned long rq_work_done = 0; | 90 | unsigned long rq_work_done = 0; |
85 | 91 | ||
92 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
93 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
94 | |||
86 | rq_work_done = fnic_rq_cmpl_handler(fnic, -1); | 95 | rq_work_done = fnic_rq_cmpl_handler(fnic, -1); |
87 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_RQ], | 96 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_RQ], |
88 | rq_work_done, | 97 | rq_work_done, |
@@ -97,6 +106,9 @@ static irqreturn_t fnic_isr_msix_wq(int irq, void *data) | |||
97 | struct fnic *fnic = data; | 106 | struct fnic *fnic = data; |
98 | unsigned long wq_work_done = 0; | 107 | unsigned long wq_work_done = 0; |
99 | 108 | ||
109 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
110 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
111 | |||
100 | wq_work_done = fnic_wq_cmpl_handler(fnic, -1); | 112 | wq_work_done = fnic_wq_cmpl_handler(fnic, -1); |
101 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ], | 113 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ], |
102 | wq_work_done, | 114 | wq_work_done, |
@@ -110,6 +122,9 @@ static irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data) | |||
110 | struct fnic *fnic = data; | 122 | struct fnic *fnic = data; |
111 | unsigned long wq_copy_work_done = 0; | 123 | unsigned long wq_copy_work_done = 0; |
112 | 124 | ||
125 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
126 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
127 | |||
113 | wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, -1); | 128 | wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, -1); |
114 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY], | 129 | vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY], |
115 | wq_copy_work_done, | 130 | wq_copy_work_done, |
@@ -122,6 +137,9 @@ static irqreturn_t fnic_isr_msix_err_notify(int irq, void *data) | |||
122 | { | 137 | { |
123 | struct fnic *fnic = data; | 138 | struct fnic *fnic = data; |
124 | 139 | ||
140 | fnic->fnic_stats.misc_stats.last_isr_time = jiffies; | ||
141 | atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count); | ||
142 | |||
125 | vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]); | 143 | vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]); |
126 | fnic_log_q_error(fnic); | 144 | fnic_log_q_error(fnic); |
127 | fnic_handle_link_event(fnic); | 145 | fnic_handle_link_event(fnic); |
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index bbf81ea3a252..be09b101b4a1 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
@@ -556,6 +556,13 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
556 | 556 | ||
557 | host->transportt = fnic_fc_transport; | 557 | host->transportt = fnic_fc_transport; |
558 | 558 | ||
559 | err = fnic_stats_debugfs_init(fnic); | ||
560 | if (err) { | ||
561 | shost_printk(KERN_ERR, fnic->lport->host, | ||
562 | "Failed to initialize debugfs for stats\n"); | ||
563 | fnic_stats_debugfs_remove(fnic); | ||
564 | } | ||
565 | |||
559 | /* Setup PCI resources */ | 566 | /* Setup PCI resources */ |
560 | pci_set_drvdata(pdev, fnic); | 567 | pci_set_drvdata(pdev, fnic); |
561 | 568 | ||
@@ -917,6 +924,7 @@ err_out_release_regions: | |||
917 | err_out_disable_device: | 924 | err_out_disable_device: |
918 | pci_disable_device(pdev); | 925 | pci_disable_device(pdev); |
919 | err_out_free_hba: | 926 | err_out_free_hba: |
927 | fnic_stats_debugfs_remove(fnic); | ||
920 | scsi_host_put(lp->host); | 928 | scsi_host_put(lp->host); |
921 | err_out: | 929 | err_out: |
922 | return err; | 930 | return err; |
@@ -969,6 +977,7 @@ static void fnic_remove(struct pci_dev *pdev) | |||
969 | 977 | ||
970 | fcoe_ctlr_destroy(&fnic->ctlr); | 978 | fcoe_ctlr_destroy(&fnic->ctlr); |
971 | fc_lport_destroy(lp); | 979 | fc_lport_destroy(lp); |
980 | fnic_stats_debugfs_remove(fnic); | ||
972 | 981 | ||
973 | /* | 982 | /* |
974 | * This stops the fnic device, masks all interrupts. Completed | 983 | * This stops the fnic device, masks all interrupts. Completed |
@@ -1014,6 +1023,14 @@ static int __init fnic_init_module(void) | |||
1014 | 1023 | ||
1015 | printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION); | 1024 | printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION); |
1016 | 1025 | ||
1026 | /* Create debugfs entries for fnic */ | ||
1027 | err = fnic_debugfs_init(); | ||
1028 | if (err < 0) { | ||
1029 | printk(KERN_ERR PFX "Failed to create fnic directory " | ||
1030 | "for tracing and stats logging\n"); | ||
1031 | fnic_debugfs_terminate(); | ||
1032 | } | ||
1033 | |||
1017 | /* Allocate memory for trace buffer */ | 1034 | /* Allocate memory for trace buffer */ |
1018 | err = fnic_trace_buf_init(); | 1035 | err = fnic_trace_buf_init(); |
1019 | if (err < 0) { | 1036 | if (err < 0) { |
@@ -1102,6 +1119,7 @@ err_create_fnic_sgl_slab_max: | |||
1102 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); | 1119 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); |
1103 | err_create_fnic_sgl_slab_dflt: | 1120 | err_create_fnic_sgl_slab_dflt: |
1104 | fnic_trace_free(); | 1121 | fnic_trace_free(); |
1122 | fnic_debugfs_terminate(); | ||
1105 | return err; | 1123 | return err; |
1106 | } | 1124 | } |
1107 | 1125 | ||
@@ -1118,6 +1136,7 @@ static void __exit fnic_cleanup_module(void) | |||
1118 | kmem_cache_destroy(fnic_io_req_cache); | 1136 | kmem_cache_destroy(fnic_io_req_cache); |
1119 | fc_release_transport(fnic_fc_transport); | 1137 | fc_release_transport(fnic_fc_transport); |
1120 | fnic_trace_free(); | 1138 | fnic_trace_free(); |
1139 | fnic_debugfs_terminate(); | ||
1121 | } | 1140 | } |
1122 | 1141 | ||
1123 | module_init(fnic_init_module); | 1142 | module_init(fnic_init_module); |
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index d014aae19134..0521436d05d6 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
@@ -226,15 +226,23 @@ int fnic_fw_reset_handler(struct fnic *fnic) | |||
226 | 226 | ||
227 | if (!vnic_wq_copy_desc_avail(wq)) | 227 | if (!vnic_wq_copy_desc_avail(wq)) |
228 | ret = -EAGAIN; | 228 | ret = -EAGAIN; |
229 | else | 229 | else { |
230 | fnic_queue_wq_copy_desc_fw_reset(wq, SCSI_NO_TAG); | 230 | fnic_queue_wq_copy_desc_fw_reset(wq, SCSI_NO_TAG); |
231 | atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
232 | if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > | ||
233 | atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) | ||
234 | atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, | ||
235 | atomic64_read( | ||
236 | &fnic->fnic_stats.fw_stats.active_fw_reqs)); | ||
237 | } | ||
231 | 238 | ||
232 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 239 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); |
233 | 240 | ||
234 | if (!ret) | 241 | if (!ret) { |
242 | atomic64_inc(&fnic->fnic_stats.reset_stats.fw_resets); | ||
235 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 243 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
236 | "Issued fw reset\n"); | 244 | "Issued fw reset\n"); |
237 | else { | 245 | } else { |
238 | fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET); | 246 | fnic_clear_state_flags(fnic, FNIC_FLAGS_FWRESET); |
239 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 247 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
240 | "Failed to issue fw reset\n"); | 248 | "Failed to issue fw reset\n"); |
@@ -291,6 +299,12 @@ int fnic_flogi_reg_handler(struct fnic *fnic, u32 fc_id) | |||
291 | fc_id, fnic->ctlr.map_dest, gw_mac); | 299 | fc_id, fnic->ctlr.map_dest, gw_mac); |
292 | } | 300 | } |
293 | 301 | ||
302 | atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
303 | if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > | ||
304 | atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) | ||
305 | atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, | ||
306 | atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); | ||
307 | |||
294 | flogi_reg_ioreq_end: | 308 | flogi_reg_ioreq_end: |
295 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 309 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); |
296 | return ret; | 310 | return ret; |
@@ -310,6 +324,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
310 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); | 324 | struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); |
311 | struct fc_rport_libfc_priv *rp = rport->dd_data; | 325 | struct fc_rport_libfc_priv *rp = rport->dd_data; |
312 | struct host_sg_desc *desc; | 326 | struct host_sg_desc *desc; |
327 | struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; | ||
313 | u8 pri_tag = 0; | 328 | u8 pri_tag = 0; |
314 | unsigned int i; | 329 | unsigned int i; |
315 | unsigned long intr_flags; | 330 | unsigned long intr_flags; |
@@ -358,6 +373,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
358 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); | 373 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); |
359 | FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | 374 | FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, |
360 | "fnic_queue_wq_copy_desc failure - no descriptors\n"); | 375 | "fnic_queue_wq_copy_desc failure - no descriptors\n"); |
376 | atomic64_inc(&misc_stats->io_cpwq_alloc_failures); | ||
361 | return SCSI_MLQUEUE_HOST_BUSY; | 377 | return SCSI_MLQUEUE_HOST_BUSY; |
362 | } | 378 | } |
363 | 379 | ||
@@ -386,6 +402,12 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, | |||
386 | rport->maxframe_size, rp->r_a_tov, | 402 | rport->maxframe_size, rp->r_a_tov, |
387 | rp->e_d_tov); | 403 | rp->e_d_tov); |
388 | 404 | ||
405 | atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
406 | if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > | ||
407 | atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) | ||
408 | atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, | ||
409 | atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); | ||
410 | |||
389 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); | 411 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); |
390 | return 0; | 412 | return 0; |
391 | } | 413 | } |
@@ -401,6 +423,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ | |||
401 | struct fc_rport *rport; | 423 | struct fc_rport *rport; |
402 | struct fnic_io_req *io_req = NULL; | 424 | struct fnic_io_req *io_req = NULL; |
403 | struct fnic *fnic = lport_priv(lp); | 425 | struct fnic *fnic = lport_priv(lp); |
426 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
404 | struct vnic_wq_copy *wq; | 427 | struct vnic_wq_copy *wq; |
405 | int ret; | 428 | int ret; |
406 | u64 cmd_trace; | 429 | u64 cmd_trace; |
@@ -414,6 +437,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ | |||
414 | rport = starget_to_rport(scsi_target(sc->device)); | 437 | rport = starget_to_rport(scsi_target(sc->device)); |
415 | ret = fc_remote_port_chkready(rport); | 438 | ret = fc_remote_port_chkready(rport); |
416 | if (ret) { | 439 | if (ret) { |
440 | atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); | ||
417 | sc->result = ret; | 441 | sc->result = ret; |
418 | done(sc); | 442 | done(sc); |
419 | return 0; | 443 | return 0; |
@@ -436,6 +460,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ | |||
436 | /* Get a new io_req for this SCSI IO */ | 460 | /* Get a new io_req for this SCSI IO */ |
437 | io_req = mempool_alloc(fnic->io_req_pool, GFP_ATOMIC); | 461 | io_req = mempool_alloc(fnic->io_req_pool, GFP_ATOMIC); |
438 | if (!io_req) { | 462 | if (!io_req) { |
463 | atomic64_inc(&fnic_stats->io_stats.alloc_failures); | ||
439 | ret = SCSI_MLQUEUE_HOST_BUSY; | 464 | ret = SCSI_MLQUEUE_HOST_BUSY; |
440 | goto out; | 465 | goto out; |
441 | } | 466 | } |
@@ -462,6 +487,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ | |||
462 | mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type], | 487 | mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type], |
463 | GFP_ATOMIC); | 488 | GFP_ATOMIC); |
464 | if (!io_req->sgl_list) { | 489 | if (!io_req->sgl_list) { |
490 | atomic64_inc(&fnic_stats->io_stats.alloc_failures); | ||
465 | ret = SCSI_MLQUEUE_HOST_BUSY; | 491 | ret = SCSI_MLQUEUE_HOST_BUSY; |
466 | scsi_dma_unmap(sc); | 492 | scsi_dma_unmap(sc); |
467 | mempool_free(io_req, fnic->io_req_pool); | 493 | mempool_free(io_req, fnic->io_req_pool); |
@@ -509,6 +535,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ | |||
509 | mempool_free(io_req, fnic->io_req_pool); | 535 | mempool_free(io_req, fnic->io_req_pool); |
510 | } | 536 | } |
511 | } else { | 537 | } else { |
538 | atomic64_inc(&fnic_stats->io_stats.active_ios); | ||
539 | atomic64_inc(&fnic_stats->io_stats.num_ios); | ||
540 | if (atomic64_read(&fnic_stats->io_stats.active_ios) > | ||
541 | atomic64_read(&fnic_stats->io_stats.max_active_ios)) | ||
542 | atomic64_set(&fnic_stats->io_stats.max_active_ios, | ||
543 | atomic64_read(&fnic_stats->io_stats.active_ios)); | ||
544 | |||
512 | /* REVISIT: Use per IO lock in the final code */ | 545 | /* REVISIT: Use per IO lock in the final code */ |
513 | CMD_FLAGS(sc) |= FNIC_IO_ISSUED; | 546 | CMD_FLAGS(sc) |= FNIC_IO_ISSUED; |
514 | } | 547 | } |
@@ -542,12 +575,18 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
542 | struct fcpio_tag tag; | 575 | struct fcpio_tag tag; |
543 | int ret = 0; | 576 | int ret = 0; |
544 | unsigned long flags; | 577 | unsigned long flags; |
578 | struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats; | ||
545 | 579 | ||
546 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 580 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); |
547 | 581 | ||
582 | atomic64_inc(&reset_stats->fw_reset_completions); | ||
583 | |||
548 | /* Clean up all outstanding io requests */ | 584 | /* Clean up all outstanding io requests */ |
549 | fnic_cleanup_io(fnic, SCSI_NO_TAG); | 585 | fnic_cleanup_io(fnic, SCSI_NO_TAG); |
550 | 586 | ||
587 | atomic64_set(&fnic->fnic_stats.fw_stats.active_fw_reqs, 0); | ||
588 | atomic64_set(&fnic->fnic_stats.io_stats.active_ios, 0); | ||
589 | |||
551 | spin_lock_irqsave(&fnic->fnic_lock, flags); | 590 | spin_lock_irqsave(&fnic->fnic_lock, flags); |
552 | 591 | ||
553 | /* fnic should be in FC_TRANS_ETH_MODE */ | 592 | /* fnic should be in FC_TRANS_ETH_MODE */ |
@@ -571,6 +610,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
571 | * reset the firmware. Free the cached flogi | 610 | * reset the firmware. Free the cached flogi |
572 | */ | 611 | */ |
573 | fnic->state = FNIC_IN_FC_MODE; | 612 | fnic->state = FNIC_IN_FC_MODE; |
613 | atomic64_inc(&reset_stats->fw_reset_failures); | ||
574 | ret = -1; | 614 | ret = -1; |
575 | } | 615 | } |
576 | } else { | 616 | } else { |
@@ -578,6 +618,7 @@ static int fnic_fcpio_fw_reset_cmpl_handler(struct fnic *fnic, | |||
578 | fnic->lport->host, | 618 | fnic->lport->host, |
579 | "Unexpected state %s while processing" | 619 | "Unexpected state %s while processing" |
580 | " reset cmpl\n", fnic_state_to_str(fnic->state)); | 620 | " reset cmpl\n", fnic_state_to_str(fnic->state)); |
621 | atomic64_inc(&reset_stats->fw_reset_failures); | ||
581 | ret = -1; | 622 | ret = -1; |
582 | } | 623 | } |
583 | 624 | ||
@@ -701,10 +742,14 @@ static inline void fnic_fcpio_ack_handler(struct fnic *fnic, | |||
701 | wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count]; | 742 | wq = &fnic->wq_copy[cq_index - fnic->raw_wq_count - fnic->rq_count]; |
702 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); | 743 | spin_lock_irqsave(&fnic->wq_copy_lock[0], flags); |
703 | 744 | ||
745 | fnic->fnic_stats.misc_stats.last_ack_time = jiffies; | ||
704 | if (is_ack_index_in_range(wq, request_out)) { | 746 | if (is_ack_index_in_range(wq, request_out)) { |
705 | fnic->fw_ack_index[0] = request_out; | 747 | fnic->fw_ack_index[0] = request_out; |
706 | fnic->fw_ack_recd[0] = 1; | 748 | fnic->fw_ack_recd[0] = 1; |
707 | } | 749 | } else |
750 | atomic64_inc( | ||
751 | &fnic->fnic_stats.misc_stats.ack_index_out_of_range); | ||
752 | |||
708 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 753 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); |
709 | FNIC_TRACE(fnic_fcpio_ack_handler, | 754 | FNIC_TRACE(fnic_fcpio_ack_handler, |
710 | fnic->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3], | 755 | fnic->lport->host->host_no, 0, 0, ox_id_tag[2], ox_id_tag[3], |
@@ -726,6 +771,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
726 | struct fcpio_icmnd_cmpl *icmnd_cmpl; | 771 | struct fcpio_icmnd_cmpl *icmnd_cmpl; |
727 | struct fnic_io_req *io_req; | 772 | struct fnic_io_req *io_req; |
728 | struct scsi_cmnd *sc; | 773 | struct scsi_cmnd *sc; |
774 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
729 | unsigned long flags; | 775 | unsigned long flags; |
730 | spinlock_t *io_lock; | 776 | spinlock_t *io_lock; |
731 | u64 cmd_trace; | 777 | u64 cmd_trace; |
@@ -746,6 +792,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
746 | sc = scsi_host_find_tag(fnic->lport->host, id); | 792 | sc = scsi_host_find_tag(fnic->lport->host, id); |
747 | WARN_ON_ONCE(!sc); | 793 | WARN_ON_ONCE(!sc); |
748 | if (!sc) { | 794 | if (!sc) { |
795 | atomic64_inc(&fnic_stats->io_stats.sc_null); | ||
749 | shost_printk(KERN_ERR, fnic->lport->host, | 796 | shost_printk(KERN_ERR, fnic->lport->host, |
750 | "icmnd_cmpl sc is null - " | 797 | "icmnd_cmpl sc is null - " |
751 | "hdr status = %s tag = 0x%x desc = 0x%p\n", | 798 | "hdr status = %s tag = 0x%x desc = 0x%p\n", |
@@ -766,6 +813,7 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
766 | io_req = (struct fnic_io_req *)CMD_SP(sc); | 813 | io_req = (struct fnic_io_req *)CMD_SP(sc); |
767 | WARN_ON_ONCE(!io_req); | 814 | WARN_ON_ONCE(!io_req); |
768 | if (!io_req) { | 815 | if (!io_req) { |
816 | atomic64_inc(&fnic_stats->io_stats.ioreq_null); | ||
769 | CMD_FLAGS(sc) |= FNIC_IO_REQ_NULL; | 817 | CMD_FLAGS(sc) |= FNIC_IO_REQ_NULL; |
770 | spin_unlock_irqrestore(io_lock, flags); | 818 | spin_unlock_irqrestore(io_lock, flags); |
771 | shost_printk(KERN_ERR, fnic->lport->host, | 819 | shost_printk(KERN_ERR, fnic->lport->host, |
@@ -824,31 +872,54 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
824 | if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER) | 872 | if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER) |
825 | xfer_len -= icmnd_cmpl->residual; | 873 | xfer_len -= icmnd_cmpl->residual; |
826 | 874 | ||
875 | if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL) | ||
876 | atomic64_inc(&fnic_stats->misc_stats.queue_fulls); | ||
827 | break; | 877 | break; |
828 | 878 | ||
829 | case FCPIO_TIMEOUT: /* request was timed out */ | 879 | case FCPIO_TIMEOUT: /* request was timed out */ |
880 | atomic64_inc(&fnic_stats->misc_stats.fcpio_timeout); | ||
830 | sc->result = (DID_TIME_OUT << 16) | icmnd_cmpl->scsi_status; | 881 | sc->result = (DID_TIME_OUT << 16) | icmnd_cmpl->scsi_status; |
831 | break; | 882 | break; |
832 | 883 | ||
833 | case FCPIO_ABORTED: /* request was aborted */ | 884 | case FCPIO_ABORTED: /* request was aborted */ |
885 | atomic64_inc(&fnic_stats->misc_stats.fcpio_aborted); | ||
834 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | 886 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; |
835 | break; | 887 | break; |
836 | 888 | ||
837 | case FCPIO_DATA_CNT_MISMATCH: /* recv/sent more/less data than exp. */ | 889 | case FCPIO_DATA_CNT_MISMATCH: /* recv/sent more/less data than exp. */ |
890 | atomic64_inc(&fnic_stats->misc_stats.data_count_mismatch); | ||
838 | scsi_set_resid(sc, icmnd_cmpl->residual); | 891 | scsi_set_resid(sc, icmnd_cmpl->residual); |
839 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | 892 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; |
840 | break; | 893 | break; |
841 | 894 | ||
842 | case FCPIO_OUT_OF_RESOURCE: /* out of resources to complete request */ | 895 | case FCPIO_OUT_OF_RESOURCE: /* out of resources to complete request */ |
896 | atomic64_inc(&fnic_stats->fw_stats.fw_out_of_resources); | ||
843 | sc->result = (DID_REQUEUE << 16) | icmnd_cmpl->scsi_status; | 897 | sc->result = (DID_REQUEUE << 16) | icmnd_cmpl->scsi_status; |
844 | break; | 898 | break; |
845 | case FCPIO_INVALID_HEADER: /* header contains invalid data */ | 899 | |
846 | case FCPIO_INVALID_PARAM: /* some parameter in request invalid */ | ||
847 | case FCPIO_REQ_NOT_SUPPORTED:/* request type is not supported */ | ||
848 | case FCPIO_IO_NOT_FOUND: /* requested I/O was not found */ | 900 | case FCPIO_IO_NOT_FOUND: /* requested I/O was not found */ |
901 | atomic64_inc(&fnic_stats->io_stats.io_not_found); | ||
902 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | ||
903 | break; | ||
904 | |||
849 | case FCPIO_SGL_INVALID: /* request was aborted due to sgl error */ | 905 | case FCPIO_SGL_INVALID: /* request was aborted due to sgl error */ |
850 | case FCPIO_MSS_INVALID: /* request was aborted due to mss error */ | 906 | atomic64_inc(&fnic_stats->misc_stats.sgl_invalid); |
907 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | ||
908 | break; | ||
909 | |||
851 | case FCPIO_FW_ERR: /* request was terminated due fw error */ | 910 | case FCPIO_FW_ERR: /* request was terminated due fw error */ |
911 | atomic64_inc(&fnic_stats->fw_stats.io_fw_errs); | ||
912 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | ||
913 | break; | ||
914 | |||
915 | case FCPIO_MSS_INVALID: /* request was aborted due to mss error */ | ||
916 | atomic64_inc(&fnic_stats->misc_stats.mss_invalid); | ||
917 | sc->result = (DID_ERROR << 16) | icmnd_cmpl->scsi_status; | ||
918 | break; | ||
919 | |||
920 | case FCPIO_INVALID_HEADER: /* header contains invalid data */ | ||
921 | case FCPIO_INVALID_PARAM: /* some parameter in request invalid */ | ||
922 | case FCPIO_REQ_NOT_SUPPORTED:/* request type is not supported */ | ||
852 | default: | 923 | default: |
853 | shost_printk(KERN_ERR, fnic->lport->host, "hdr status = %s\n", | 924 | shost_printk(KERN_ERR, fnic->lport->host, "hdr status = %s\n", |
854 | fnic_fcpio_status_to_str(hdr_status)); | 925 | fnic_fcpio_status_to_str(hdr_status)); |
@@ -856,6 +927,11 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
856 | break; | 927 | break; |
857 | } | 928 | } |
858 | 929 | ||
930 | if (hdr_status != FCPIO_SUCCESS) { | ||
931 | atomic64_inc(&fnic_stats->io_stats.io_failures); | ||
932 | shost_printk(KERN_ERR, fnic->lport->host, "hdr status = %s\n", | ||
933 | fnic_fcpio_status_to_str(hdr_status)); | ||
934 | } | ||
859 | /* Break link with the SCSI command */ | 935 | /* Break link with the SCSI command */ |
860 | CMD_SP(sc) = NULL; | 936 | CMD_SP(sc) = NULL; |
861 | CMD_FLAGS(sc) |= FNIC_IO_DONE; | 937 | CMD_FLAGS(sc) |= FNIC_IO_DONE; |
@@ -889,6 +965,12 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, | |||
889 | } else | 965 | } else |
890 | fnic->lport->host_stats.fcp_control_requests++; | 966 | fnic->lport->host_stats.fcp_control_requests++; |
891 | 967 | ||
968 | atomic64_dec(&fnic_stats->io_stats.active_ios); | ||
969 | if (atomic64_read(&fnic->io_cmpl_skip)) | ||
970 | atomic64_dec(&fnic->io_cmpl_skip); | ||
971 | else | ||
972 | atomic64_inc(&fnic_stats->io_stats.io_completions); | ||
973 | |||
892 | /* Call SCSI completion function to complete the IO */ | 974 | /* Call SCSI completion function to complete the IO */ |
893 | if (sc->scsi_done) | 975 | if (sc->scsi_done) |
894 | sc->scsi_done(sc); | 976 | sc->scsi_done(sc); |
@@ -906,6 +988,10 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, | |||
906 | u32 id; | 988 | u32 id; |
907 | struct scsi_cmnd *sc; | 989 | struct scsi_cmnd *sc; |
908 | struct fnic_io_req *io_req; | 990 | struct fnic_io_req *io_req; |
991 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
992 | struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; | ||
993 | struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats; | ||
994 | struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; | ||
909 | unsigned long flags; | 995 | unsigned long flags; |
910 | spinlock_t *io_lock; | 996 | spinlock_t *io_lock; |
911 | unsigned long start_time; | 997 | unsigned long start_time; |
@@ -923,6 +1009,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, | |||
923 | sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); | 1009 | sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); |
924 | WARN_ON_ONCE(!sc); | 1010 | WARN_ON_ONCE(!sc); |
925 | if (!sc) { | 1011 | if (!sc) { |
1012 | atomic64_inc(&fnic_stats->io_stats.sc_null); | ||
926 | shost_printk(KERN_ERR, fnic->lport->host, | 1013 | shost_printk(KERN_ERR, fnic->lport->host, |
927 | "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", | 1014 | "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", |
928 | fnic_fcpio_status_to_str(hdr_status), id); | 1015 | fnic_fcpio_status_to_str(hdr_status), id); |
@@ -933,6 +1020,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, | |||
933 | io_req = (struct fnic_io_req *)CMD_SP(sc); | 1020 | io_req = (struct fnic_io_req *)CMD_SP(sc); |
934 | WARN_ON_ONCE(!io_req); | 1021 | WARN_ON_ONCE(!io_req); |
935 | if (!io_req) { | 1022 | if (!io_req) { |
1023 | atomic64_inc(&fnic_stats->io_stats.ioreq_null); | ||
936 | spin_unlock_irqrestore(io_lock, flags); | 1024 | spin_unlock_irqrestore(io_lock, flags); |
937 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL; | 1025 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL; |
938 | shost_printk(KERN_ERR, fnic->lport->host, | 1026 | shost_printk(KERN_ERR, fnic->lport->host, |
@@ -957,6 +1045,31 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, | |||
957 | spin_unlock_irqrestore(io_lock, flags); | 1045 | spin_unlock_irqrestore(io_lock, flags); |
958 | } else if (id & FNIC_TAG_ABORT) { | 1046 | } else if (id & FNIC_TAG_ABORT) { |
959 | /* Completion of abort cmd */ | 1047 | /* Completion of abort cmd */ |
1048 | switch (hdr_status) { | ||
1049 | case FCPIO_SUCCESS: | ||
1050 | break; | ||
1051 | case FCPIO_TIMEOUT: | ||
1052 | if (CMD_FLAGS(sc) & FNIC_IO_ABTS_ISSUED) | ||
1053 | atomic64_inc(&abts_stats->abort_fw_timeouts); | ||
1054 | else | ||
1055 | atomic64_inc( | ||
1056 | &term_stats->terminate_fw_timeouts); | ||
1057 | break; | ||
1058 | case FCPIO_IO_NOT_FOUND: | ||
1059 | if (CMD_FLAGS(sc) & FNIC_IO_ABTS_ISSUED) | ||
1060 | atomic64_inc(&abts_stats->abort_io_not_found); | ||
1061 | else | ||
1062 | atomic64_inc( | ||
1063 | &term_stats->terminate_io_not_found); | ||
1064 | break; | ||
1065 | default: | ||
1066 | if (CMD_FLAGS(sc) & FNIC_IO_ABTS_ISSUED) | ||
1067 | atomic64_inc(&abts_stats->abort_failures); | ||
1068 | else | ||
1069 | atomic64_inc( | ||
1070 | &term_stats->terminate_failures); | ||
1071 | break; | ||
1072 | } | ||
960 | if (CMD_STATE(sc) != FNIC_IOREQ_ABTS_PENDING) { | 1073 | if (CMD_STATE(sc) != FNIC_IOREQ_ABTS_PENDING) { |
961 | /* This is a late completion. Ignore it */ | 1074 | /* This is a late completion. Ignore it */ |
962 | spin_unlock_irqrestore(io_lock, flags); | 1075 | spin_unlock_irqrestore(io_lock, flags); |
@@ -964,6 +1077,16 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, | |||
964 | } | 1077 | } |
965 | CMD_ABTS_STATUS(sc) = hdr_status; | 1078 | CMD_ABTS_STATUS(sc) = hdr_status; |
966 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE; | 1079 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_DONE; |
1080 | |||
1081 | atomic64_dec(&fnic_stats->io_stats.active_ios); | ||
1082 | if (atomic64_read(&fnic->io_cmpl_skip)) | ||
1083 | atomic64_dec(&fnic->io_cmpl_skip); | ||
1084 | else | ||
1085 | atomic64_inc(&fnic_stats->io_stats.io_completions); | ||
1086 | |||
1087 | if (!(CMD_FLAGS(sc) & (FNIC_IO_ABORTED | FNIC_IO_DONE))) | ||
1088 | atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls); | ||
1089 | |||
967 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 1090 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
968 | "abts cmpl recd. id %d status %s\n", | 1091 | "abts cmpl recd. id %d status %s\n", |
969 | (int)(id & FNIC_TAG_MASK), | 1092 | (int)(id & FNIC_TAG_MASK), |
@@ -1067,6 +1190,18 @@ static int fnic_fcpio_cmpl_handler(struct vnic_dev *vdev, | |||
1067 | struct fnic *fnic = vnic_dev_priv(vdev); | 1190 | struct fnic *fnic = vnic_dev_priv(vdev); |
1068 | 1191 | ||
1069 | switch (desc->hdr.type) { | 1192 | switch (desc->hdr.type) { |
1193 | case FCPIO_ICMND_CMPL: /* fw completed a command */ | ||
1194 | case FCPIO_ITMF_CMPL: /* fw completed itmf (abort cmd, lun reset)*/ | ||
1195 | case FCPIO_FLOGI_REG_CMPL: /* fw completed flogi_reg */ | ||
1196 | case FCPIO_FLOGI_FIP_REG_CMPL: /* fw completed flogi_fip_reg */ | ||
1197 | case FCPIO_RESET_CMPL: /* fw completed reset */ | ||
1198 | atomic64_dec(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
1199 | break; | ||
1200 | default: | ||
1201 | break; | ||
1202 | } | ||
1203 | |||
1204 | switch (desc->hdr.type) { | ||
1070 | case FCPIO_ACK: /* fw copied copy wq desc to its queue */ | 1205 | case FCPIO_ACK: /* fw copied copy wq desc to its queue */ |
1071 | fnic_fcpio_ack_handler(fnic, cq_index, desc); | 1206 | fnic_fcpio_ack_handler(fnic, cq_index, desc); |
1072 | break; | 1207 | break; |
@@ -1126,6 +1261,7 @@ static void fnic_cleanup_io(struct fnic *fnic, int exclude_id) | |||
1126 | struct scsi_cmnd *sc; | 1261 | struct scsi_cmnd *sc; |
1127 | spinlock_t *io_lock; | 1262 | spinlock_t *io_lock; |
1128 | unsigned long start_time = 0; | 1263 | unsigned long start_time = 0; |
1264 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | ||
1129 | 1265 | ||
1130 | for (i = 0; i < fnic->fnic_max_tag_id; i++) { | 1266 | for (i = 0; i < fnic->fnic_max_tag_id; i++) { |
1131 | if (i == exclude_id) | 1267 | if (i == exclude_id) |
@@ -1179,6 +1315,11 @@ cleanup_scsi_cmd: | |||
1179 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "fnic_cleanup_io:" | 1315 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, "fnic_cleanup_io:" |
1180 | " DID_TRANSPORT_DISRUPTED\n"); | 1316 | " DID_TRANSPORT_DISRUPTED\n"); |
1181 | 1317 | ||
1318 | if (atomic64_read(&fnic->io_cmpl_skip)) | ||
1319 | atomic64_dec(&fnic->io_cmpl_skip); | ||
1320 | else | ||
1321 | atomic64_inc(&fnic_stats->io_stats.io_completions); | ||
1322 | |||
1182 | /* Complete the command to SCSI */ | 1323 | /* Complete the command to SCSI */ |
1183 | if (sc->scsi_done) { | 1324 | if (sc->scsi_done) { |
1184 | FNIC_TRACE(fnic_cleanup_io, | 1325 | FNIC_TRACE(fnic_cleanup_io, |
@@ -1262,6 +1403,7 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag, | |||
1262 | { | 1403 | { |
1263 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; | 1404 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; |
1264 | struct Scsi_Host *host = fnic->lport->host; | 1405 | struct Scsi_Host *host = fnic->lport->host; |
1406 | struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; | ||
1265 | unsigned long flags; | 1407 | unsigned long flags; |
1266 | 1408 | ||
1267 | spin_lock_irqsave(host->host_lock, flags); | 1409 | spin_lock_irqsave(host->host_lock, flags); |
@@ -1283,12 +1425,19 @@ static inline int fnic_queue_abort_io_req(struct fnic *fnic, int tag, | |||
1283 | atomic_dec(&fnic->in_flight); | 1425 | atomic_dec(&fnic->in_flight); |
1284 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 1426 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
1285 | "fnic_queue_abort_io_req: failure: no descriptors\n"); | 1427 | "fnic_queue_abort_io_req: failure: no descriptors\n"); |
1428 | atomic64_inc(&misc_stats->abts_cpwq_alloc_failures); | ||
1286 | return 1; | 1429 | return 1; |
1287 | } | 1430 | } |
1288 | fnic_queue_wq_copy_desc_itmf(wq, tag | FNIC_TAG_ABORT, | 1431 | fnic_queue_wq_copy_desc_itmf(wq, tag | FNIC_TAG_ABORT, |
1289 | 0, task_req, tag, fc_lun, io_req->port_id, | 1432 | 0, task_req, tag, fc_lun, io_req->port_id, |
1290 | fnic->config.ra_tov, fnic->config.ed_tov); | 1433 | fnic->config.ra_tov, fnic->config.ed_tov); |
1291 | 1434 | ||
1435 | atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
1436 | if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > | ||
1437 | atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) | ||
1438 | atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, | ||
1439 | atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); | ||
1440 | |||
1292 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); | 1441 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], flags); |
1293 | atomic_dec(&fnic->in_flight); | 1442 | atomic_dec(&fnic->in_flight); |
1294 | 1443 | ||
@@ -1299,10 +1448,13 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id) | |||
1299 | { | 1448 | { |
1300 | int tag; | 1449 | int tag; |
1301 | int abt_tag; | 1450 | int abt_tag; |
1451 | int term_cnt = 0; | ||
1302 | struct fnic_io_req *io_req; | 1452 | struct fnic_io_req *io_req; |
1303 | spinlock_t *io_lock; | 1453 | spinlock_t *io_lock; |
1304 | unsigned long flags; | 1454 | unsigned long flags; |
1305 | struct scsi_cmnd *sc; | 1455 | struct scsi_cmnd *sc; |
1456 | struct reset_stats *reset_stats = &fnic->fnic_stats.reset_stats; | ||
1457 | struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats; | ||
1306 | struct scsi_lun fc_lun; | 1458 | struct scsi_lun fc_lun; |
1307 | enum fnic_ioreq_state old_ioreq_state; | 1459 | enum fnic_ioreq_state old_ioreq_state; |
1308 | 1460 | ||
@@ -1366,6 +1518,7 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id) | |||
1366 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING; | 1518 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING; |
1367 | CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE; | 1519 | CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE; |
1368 | if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) { | 1520 | if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) { |
1521 | atomic64_inc(&reset_stats->device_reset_terminates); | ||
1369 | abt_tag = (tag | FNIC_TAG_DEV_RST); | 1522 | abt_tag = (tag | FNIC_TAG_DEV_RST); |
1370 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 1523 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
1371 | "fnic_rport_exch_reset dev rst sc 0x%p\n", | 1524 | "fnic_rport_exch_reset dev rst sc 0x%p\n", |
@@ -1402,8 +1555,12 @@ static void fnic_rport_exch_reset(struct fnic *fnic, u32 port_id) | |||
1402 | else | 1555 | else |
1403 | CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED; | 1556 | CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED; |
1404 | spin_unlock_irqrestore(io_lock, flags); | 1557 | spin_unlock_irqrestore(io_lock, flags); |
1558 | atomic64_inc(&term_stats->terminates); | ||
1559 | term_cnt++; | ||
1405 | } | 1560 | } |
1406 | } | 1561 | } |
1562 | if (term_cnt > atomic64_read(&term_stats->max_terminates)) | ||
1563 | atomic64_set(&term_stats->max_terminates, term_cnt); | ||
1407 | 1564 | ||
1408 | } | 1565 | } |
1409 | 1566 | ||
@@ -1411,6 +1568,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1411 | { | 1568 | { |
1412 | int tag; | 1569 | int tag; |
1413 | int abt_tag; | 1570 | int abt_tag; |
1571 | int term_cnt = 0; | ||
1414 | struct fnic_io_req *io_req; | 1572 | struct fnic_io_req *io_req; |
1415 | spinlock_t *io_lock; | 1573 | spinlock_t *io_lock; |
1416 | unsigned long flags; | 1574 | unsigned long flags; |
@@ -1420,6 +1578,8 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1420 | struct fc_lport *lport; | 1578 | struct fc_lport *lport; |
1421 | struct fnic *fnic; | 1579 | struct fnic *fnic; |
1422 | struct fc_rport *cmd_rport; | 1580 | struct fc_rport *cmd_rport; |
1581 | struct reset_stats *reset_stats; | ||
1582 | struct terminate_stats *term_stats; | ||
1423 | enum fnic_ioreq_state old_ioreq_state; | 1583 | enum fnic_ioreq_state old_ioreq_state; |
1424 | 1584 | ||
1425 | if (!rport) { | 1585 | if (!rport) { |
@@ -1448,6 +1608,9 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1448 | if (fnic->in_remove) | 1608 | if (fnic->in_remove) |
1449 | return; | 1609 | return; |
1450 | 1610 | ||
1611 | reset_stats = &fnic->fnic_stats.reset_stats; | ||
1612 | term_stats = &fnic->fnic_stats.term_stats; | ||
1613 | |||
1451 | for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) { | 1614 | for (tag = 0; tag < fnic->fnic_max_tag_id; tag++) { |
1452 | abt_tag = tag; | 1615 | abt_tag = tag; |
1453 | io_lock = fnic_io_lock_tag(fnic, tag); | 1616 | io_lock = fnic_io_lock_tag(fnic, tag); |
@@ -1504,6 +1667,7 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1504 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING; | 1667 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_PENDING; |
1505 | CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE; | 1668 | CMD_ABTS_STATUS(sc) = FCPIO_INVALID_CODE; |
1506 | if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) { | 1669 | if (CMD_FLAGS(sc) & FNIC_DEVICE_RESET) { |
1670 | atomic64_inc(&reset_stats->device_reset_terminates); | ||
1507 | abt_tag = (tag | FNIC_TAG_DEV_RST); | 1671 | abt_tag = (tag | FNIC_TAG_DEV_RST); |
1508 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 1672 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
1509 | "fnic_terminate_rport_io dev rst sc 0x%p\n", sc); | 1673 | "fnic_terminate_rport_io dev rst sc 0x%p\n", sc); |
@@ -1540,8 +1704,12 @@ void fnic_terminate_rport_io(struct fc_rport *rport) | |||
1540 | else | 1704 | else |
1541 | CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED; | 1705 | CMD_FLAGS(sc) |= FNIC_IO_INTERNAL_TERM_ISSUED; |
1542 | spin_unlock_irqrestore(io_lock, flags); | 1706 | spin_unlock_irqrestore(io_lock, flags); |
1707 | atomic64_inc(&term_stats->terminates); | ||
1708 | term_cnt++; | ||
1543 | } | 1709 | } |
1544 | } | 1710 | } |
1711 | if (term_cnt > atomic64_read(&term_stats->max_terminates)) | ||
1712 | atomic64_set(&term_stats->max_terminates, term_cnt); | ||
1545 | 1713 | ||
1546 | } | 1714 | } |
1547 | 1715 | ||
@@ -1562,6 +1730,9 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1562 | int ret = SUCCESS; | 1730 | int ret = SUCCESS; |
1563 | u32 task_req = 0; | 1731 | u32 task_req = 0; |
1564 | struct scsi_lun fc_lun; | 1732 | struct scsi_lun fc_lun; |
1733 | struct fnic_stats *fnic_stats; | ||
1734 | struct abort_stats *abts_stats; | ||
1735 | struct terminate_stats *term_stats; | ||
1565 | int tag; | 1736 | int tag; |
1566 | DECLARE_COMPLETION_ONSTACK(tm_done); | 1737 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1567 | 1738 | ||
@@ -1572,6 +1743,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1572 | lp = shost_priv(sc->device->host); | 1743 | lp = shost_priv(sc->device->host); |
1573 | 1744 | ||
1574 | fnic = lport_priv(lp); | 1745 | fnic = lport_priv(lp); |
1746 | fnic_stats = &fnic->fnic_stats; | ||
1747 | abts_stats = &fnic->fnic_stats.abts_stats; | ||
1748 | term_stats = &fnic->fnic_stats.term_stats; | ||
1749 | |||
1575 | rport = starget_to_rport(scsi_target(sc->device)); | 1750 | rport = starget_to_rport(scsi_target(sc->device)); |
1576 | tag = sc->request->tag; | 1751 | tag = sc->request->tag; |
1577 | FNIC_SCSI_DBG(KERN_DEBUG, | 1752 | FNIC_SCSI_DBG(KERN_DEBUG, |
@@ -1630,8 +1805,10 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1630 | */ | 1805 | */ |
1631 | if (fc_remote_port_chkready(rport) == 0) | 1806 | if (fc_remote_port_chkready(rport) == 0) |
1632 | task_req = FCPIO_ITMF_ABT_TASK; | 1807 | task_req = FCPIO_ITMF_ABT_TASK; |
1633 | else | 1808 | else { |
1809 | atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); | ||
1634 | task_req = FCPIO_ITMF_ABT_TASK_TERM; | 1810 | task_req = FCPIO_ITMF_ABT_TASK_TERM; |
1811 | } | ||
1635 | 1812 | ||
1636 | /* Now queue the abort command to firmware */ | 1813 | /* Now queue the abort command to firmware */ |
1637 | int_to_scsilun(sc->device->lun, &fc_lun); | 1814 | int_to_scsilun(sc->device->lun, &fc_lun); |
@@ -1646,10 +1823,13 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1646 | ret = FAILED; | 1823 | ret = FAILED; |
1647 | goto fnic_abort_cmd_end; | 1824 | goto fnic_abort_cmd_end; |
1648 | } | 1825 | } |
1649 | if (task_req == FCPIO_ITMF_ABT_TASK) | 1826 | if (task_req == FCPIO_ITMF_ABT_TASK) { |
1650 | CMD_FLAGS(sc) |= FNIC_IO_ABTS_ISSUED; | 1827 | CMD_FLAGS(sc) |= FNIC_IO_ABTS_ISSUED; |
1651 | else | 1828 | atomic64_inc(&fnic_stats->abts_stats.aborts); |
1829 | } else { | ||
1652 | CMD_FLAGS(sc) |= FNIC_IO_TERM_ISSUED; | 1830 | CMD_FLAGS(sc) |= FNIC_IO_TERM_ISSUED; |
1831 | atomic64_inc(&fnic_stats->term_stats.terminates); | ||
1832 | } | ||
1653 | 1833 | ||
1654 | /* | 1834 | /* |
1655 | * We queued an abort IO, wait for its completion. | 1835 | * We queued an abort IO, wait for its completion. |
@@ -1667,6 +1847,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1667 | 1847 | ||
1668 | io_req = (struct fnic_io_req *)CMD_SP(sc); | 1848 | io_req = (struct fnic_io_req *)CMD_SP(sc); |
1669 | if (!io_req) { | 1849 | if (!io_req) { |
1850 | atomic64_inc(&fnic_stats->io_stats.ioreq_null); | ||
1670 | spin_unlock_irqrestore(io_lock, flags); | 1851 | spin_unlock_irqrestore(io_lock, flags); |
1671 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL; | 1852 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_REQ_NULL; |
1672 | ret = FAILED; | 1853 | ret = FAILED; |
@@ -1677,6 +1858,15 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
1677 | /* fw did not complete abort, timed out */ | 1858 | /* fw did not complete abort, timed out */ |
1678 | if (CMD_ABTS_STATUS(sc) == FCPIO_INVALID_CODE) { | 1859 | if (CMD_ABTS_STATUS(sc) == FCPIO_INVALID_CODE) { |
1679 | spin_unlock_irqrestore(io_lock, flags); | 1860 | spin_unlock_irqrestore(io_lock, flags); |
1861 | if (task_req == FCPIO_ITMF_ABT_TASK) { | ||
1862 | FNIC_SCSI_DBG(KERN_INFO, | ||
1863 | fnic->lport->host, "Abort Driver Timeout\n"); | ||
1864 | atomic64_inc(&abts_stats->abort_drv_timeouts); | ||
1865 | } else { | ||
1866 | FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | ||
1867 | "Terminate Driver Timeout\n"); | ||
1868 | atomic64_inc(&term_stats->terminate_drv_timeouts); | ||
1869 | } | ||
1680 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_TIMED_OUT; | 1870 | CMD_FLAGS(sc) |= FNIC_IO_ABT_TERM_TIMED_OUT; |
1681 | ret = FAILED; | 1871 | ret = FAILED; |
1682 | goto fnic_abort_cmd_end; | 1872 | goto fnic_abort_cmd_end; |
@@ -1721,6 +1911,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, | |||
1721 | { | 1911 | { |
1722 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; | 1912 | struct vnic_wq_copy *wq = &fnic->wq_copy[0]; |
1723 | struct Scsi_Host *host = fnic->lport->host; | 1913 | struct Scsi_Host *host = fnic->lport->host; |
1914 | struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats; | ||
1724 | struct scsi_lun fc_lun; | 1915 | struct scsi_lun fc_lun; |
1725 | int ret = 0; | 1916 | int ret = 0; |
1726 | unsigned long intr_flags; | 1917 | unsigned long intr_flags; |
@@ -1742,6 +1933,7 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, | |||
1742 | if (!vnic_wq_copy_desc_avail(wq)) { | 1933 | if (!vnic_wq_copy_desc_avail(wq)) { |
1743 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 1934 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
1744 | "queue_dr_io_req failure - no descriptors\n"); | 1935 | "queue_dr_io_req failure - no descriptors\n"); |
1936 | atomic64_inc(&misc_stats->devrst_cpwq_alloc_failures); | ||
1745 | ret = -EAGAIN; | 1937 | ret = -EAGAIN; |
1746 | goto lr_io_req_end; | 1938 | goto lr_io_req_end; |
1747 | } | 1939 | } |
@@ -1754,6 +1946,12 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, | |||
1754 | fc_lun.scsi_lun, io_req->port_id, | 1946 | fc_lun.scsi_lun, io_req->port_id, |
1755 | fnic->config.ra_tov, fnic->config.ed_tov); | 1947 | fnic->config.ra_tov, fnic->config.ed_tov); |
1756 | 1948 | ||
1949 | atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs); | ||
1950 | if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) > | ||
1951 | atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs)) | ||
1952 | atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs, | ||
1953 | atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs)); | ||
1954 | |||
1757 | lr_io_req_end: | 1955 | lr_io_req_end: |
1758 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); | 1956 | spin_unlock_irqrestore(&fnic->wq_copy_lock[0], intr_flags); |
1759 | atomic_dec(&fnic->in_flight); | 1957 | atomic_dec(&fnic->in_flight); |
@@ -1988,6 +2186,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
1988 | unsigned long flags; | 2186 | unsigned long flags; |
1989 | unsigned long start_time = 0; | 2187 | unsigned long start_time = 0; |
1990 | struct scsi_lun fc_lun; | 2188 | struct scsi_lun fc_lun; |
2189 | struct fnic_stats *fnic_stats; | ||
2190 | struct reset_stats *reset_stats; | ||
1991 | int tag = 0; | 2191 | int tag = 0; |
1992 | DECLARE_COMPLETION_ONSTACK(tm_done); | 2192 | DECLARE_COMPLETION_ONSTACK(tm_done); |
1993 | int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/ | 2193 | int tag_gen_flag = 0; /*to track tags allocated by fnic driver*/ |
@@ -1999,6 +2199,10 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
1999 | lp = shost_priv(sc->device->host); | 2199 | lp = shost_priv(sc->device->host); |
2000 | 2200 | ||
2001 | fnic = lport_priv(lp); | 2201 | fnic = lport_priv(lp); |
2202 | fnic_stats = &fnic->fnic_stats; | ||
2203 | reset_stats = &fnic->fnic_stats.reset_stats; | ||
2204 | |||
2205 | atomic64_inc(&reset_stats->device_resets); | ||
2002 | 2206 | ||
2003 | rport = starget_to_rport(scsi_target(sc->device)); | 2207 | rport = starget_to_rport(scsi_target(sc->device)); |
2004 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 2208 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
@@ -2009,8 +2213,10 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
2009 | goto fnic_device_reset_end; | 2213 | goto fnic_device_reset_end; |
2010 | 2214 | ||
2011 | /* Check if remote port up */ | 2215 | /* Check if remote port up */ |
2012 | if (fc_remote_port_chkready(rport)) | 2216 | if (fc_remote_port_chkready(rport)) { |
2217 | atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); | ||
2013 | goto fnic_device_reset_end; | 2218 | goto fnic_device_reset_end; |
2219 | } | ||
2014 | 2220 | ||
2015 | CMD_FLAGS(sc) = FNIC_DEVICE_RESET; | 2221 | CMD_FLAGS(sc) = FNIC_DEVICE_RESET; |
2016 | /* Allocate tag if not present */ | 2222 | /* Allocate tag if not present */ |
@@ -2086,6 +2292,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) | |||
2086 | * gets cleaned up during higher levels of EH | 2292 | * gets cleaned up during higher levels of EH |
2087 | */ | 2293 | */ |
2088 | if (status == FCPIO_INVALID_CODE) { | 2294 | if (status == FCPIO_INVALID_CODE) { |
2295 | atomic64_inc(&reset_stats->device_reset_timeouts); | ||
2089 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 2296 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
2090 | "Device reset timed out\n"); | 2297 | "Device reset timed out\n"); |
2091 | CMD_FLAGS(sc) |= FNIC_DEV_RST_TIMED_OUT; | 2298 | CMD_FLAGS(sc) |= FNIC_DEV_RST_TIMED_OUT; |
@@ -2199,6 +2406,10 @@ fnic_device_reset_end: | |||
2199 | "Returning from device reset %s\n", | 2406 | "Returning from device reset %s\n", |
2200 | (ret == SUCCESS) ? | 2407 | (ret == SUCCESS) ? |
2201 | "SUCCESS" : "FAILED"); | 2408 | "SUCCESS" : "FAILED"); |
2409 | |||
2410 | if (ret == FAILED) | ||
2411 | atomic64_inc(&reset_stats->device_reset_failures); | ||
2412 | |||
2202 | return ret; | 2413 | return ret; |
2203 | } | 2414 | } |
2204 | 2415 | ||
@@ -2207,26 +2418,34 @@ int fnic_reset(struct Scsi_Host *shost) | |||
2207 | { | 2418 | { |
2208 | struct fc_lport *lp; | 2419 | struct fc_lport *lp; |
2209 | struct fnic *fnic; | 2420 | struct fnic *fnic; |
2210 | int ret = SUCCESS; | 2421 | int ret = 0; |
2422 | struct reset_stats *reset_stats; | ||
2211 | 2423 | ||
2212 | lp = shost_priv(shost); | 2424 | lp = shost_priv(shost); |
2213 | fnic = lport_priv(lp); | 2425 | fnic = lport_priv(lp); |
2426 | reset_stats = &fnic->fnic_stats.reset_stats; | ||
2214 | 2427 | ||
2215 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 2428 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
2216 | "fnic_reset called\n"); | 2429 | "fnic_reset called\n"); |
2217 | 2430 | ||
2431 | atomic64_inc(&reset_stats->fnic_resets); | ||
2432 | |||
2218 | /* | 2433 | /* |
2219 | * Reset local port, this will clean up libFC exchanges, | 2434 | * Reset local port, this will clean up libFC exchanges, |
2220 | * reset remote port sessions, and if link is up, begin flogi | 2435 | * reset remote port sessions, and if link is up, begin flogi |
2221 | */ | 2436 | */ |
2222 | if (lp->tt.lport_reset(lp)) | 2437 | ret = lp->tt.lport_reset(lp); |
2223 | ret = FAILED; | ||
2224 | 2438 | ||
2225 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 2439 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
2226 | "Returning from fnic reset %s\n", | 2440 | "Returning from fnic reset %s\n", |
2227 | (ret == SUCCESS) ? | 2441 | (ret == 0) ? |
2228 | "SUCCESS" : "FAILED"); | 2442 | "SUCCESS" : "FAILED"); |
2229 | 2443 | ||
2444 | if (ret == 0) | ||
2445 | atomic64_inc(&reset_stats->fnic_reset_completions); | ||
2446 | else | ||
2447 | atomic64_inc(&reset_stats->fnic_reset_failures); | ||
2448 | |||
2230 | return ret; | 2449 | return ret; |
2231 | } | 2450 | } |
2232 | 2451 | ||
@@ -2251,7 +2470,7 @@ int fnic_host_reset(struct scsi_cmnd *sc) | |||
2251 | * scsi-ml tries to send a TUR to every device if host reset is | 2470 | * scsi-ml tries to send a TUR to every device if host reset is |
2252 | * successful, so before returning to scsi, fabric should be up | 2471 | * successful, so before returning to scsi, fabric should be up |
2253 | */ | 2472 | */ |
2254 | ret = fnic_reset(shost); | 2473 | ret = (fnic_reset(shost) == 0) ? SUCCESS : FAILED; |
2255 | if (ret == SUCCESS) { | 2474 | if (ret == SUCCESS) { |
2256 | wait_host_tmo = jiffies + FNIC_HOST_RESET_SETTLE_TIME * HZ; | 2475 | wait_host_tmo = jiffies + FNIC_HOST_RESET_SETTLE_TIME * HZ; |
2257 | ret = FAILED; | 2476 | ret = FAILED; |
diff --git a/drivers/scsi/fnic/fnic_stats.h b/drivers/scsi/fnic/fnic_stats.h new file mode 100644 index 000000000000..540cceb843cd --- /dev/null +++ b/drivers/scsi/fnic/fnic_stats.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Cisco Systems, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you may redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; version 2 of the License. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
9 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
10 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
11 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
12 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
15 | * SOFTWARE. | ||
16 | */ | ||
17 | #ifndef _FNIC_STATS_H_ | ||
18 | #define _FNIC_STATS_H_ | ||
19 | struct io_path_stats { | ||
20 | atomic64_t active_ios; | ||
21 | atomic64_t max_active_ios; | ||
22 | atomic64_t io_completions; | ||
23 | atomic64_t io_failures; | ||
24 | atomic64_t ioreq_null; | ||
25 | atomic64_t alloc_failures; | ||
26 | atomic64_t sc_null; | ||
27 | atomic64_t io_not_found; | ||
28 | atomic64_t num_ios; | ||
29 | }; | ||
30 | |||
31 | struct abort_stats { | ||
32 | atomic64_t aborts; | ||
33 | atomic64_t abort_failures; | ||
34 | atomic64_t abort_drv_timeouts; | ||
35 | atomic64_t abort_fw_timeouts; | ||
36 | atomic64_t abort_io_not_found; | ||
37 | }; | ||
38 | |||
39 | struct terminate_stats { | ||
40 | atomic64_t terminates; | ||
41 | atomic64_t max_terminates; | ||
42 | atomic64_t terminate_drv_timeouts; | ||
43 | atomic64_t terminate_fw_timeouts; | ||
44 | atomic64_t terminate_io_not_found; | ||
45 | atomic64_t terminate_failures; | ||
46 | }; | ||
47 | |||
48 | struct reset_stats { | ||
49 | atomic64_t device_resets; | ||
50 | atomic64_t device_reset_failures; | ||
51 | atomic64_t device_reset_aborts; | ||
52 | atomic64_t device_reset_timeouts; | ||
53 | atomic64_t device_reset_terminates; | ||
54 | atomic64_t fw_resets; | ||
55 | atomic64_t fw_reset_completions; | ||
56 | atomic64_t fw_reset_failures; | ||
57 | atomic64_t fnic_resets; | ||
58 | atomic64_t fnic_reset_completions; | ||
59 | atomic64_t fnic_reset_failures; | ||
60 | }; | ||
61 | |||
62 | struct fw_stats { | ||
63 | atomic64_t active_fw_reqs; | ||
64 | atomic64_t max_fw_reqs; | ||
65 | atomic64_t fw_out_of_resources; | ||
66 | atomic64_t io_fw_errs; | ||
67 | }; | ||
68 | |||
69 | struct vlan_stats { | ||
70 | atomic64_t vlan_disc_reqs; | ||
71 | atomic64_t resp_withno_vlanID; | ||
72 | atomic64_t sol_expiry_count; | ||
73 | atomic64_t flogi_rejects; | ||
74 | }; | ||
75 | |||
76 | struct misc_stats { | ||
77 | u64 last_isr_time; | ||
78 | u64 last_ack_time; | ||
79 | atomic64_t isr_count; | ||
80 | atomic64_t max_cq_entries; | ||
81 | atomic64_t ack_index_out_of_range; | ||
82 | atomic64_t data_count_mismatch; | ||
83 | atomic64_t fcpio_timeout; | ||
84 | atomic64_t fcpio_aborted; | ||
85 | atomic64_t sgl_invalid; | ||
86 | atomic64_t mss_invalid; | ||
87 | atomic64_t abts_cpwq_alloc_failures; | ||
88 | atomic64_t devrst_cpwq_alloc_failures; | ||
89 | atomic64_t io_cpwq_alloc_failures; | ||
90 | atomic64_t no_icmnd_itmf_cmpls; | ||
91 | atomic64_t queue_fulls; | ||
92 | atomic64_t rport_not_ready; | ||
93 | atomic64_t frame_errors; | ||
94 | }; | ||
95 | |||
96 | struct fnic_stats { | ||
97 | struct io_path_stats io_stats; | ||
98 | struct abort_stats abts_stats; | ||
99 | struct terminate_stats term_stats; | ||
100 | struct reset_stats reset_stats; | ||
101 | struct fw_stats fw_stats; | ||
102 | struct vlan_stats vlan_stats; | ||
103 | struct misc_stats misc_stats; | ||
104 | }; | ||
105 | |||
106 | struct stats_debug_info { | ||
107 | char *debug_buffer; | ||
108 | void *i_private; | ||
109 | int buf_size; | ||
110 | int buffer_len; | ||
111 | }; | ||
112 | |||
113 | int fnic_get_stats_data(struct stats_debug_info *, struct fnic_stats *); | ||
114 | int fnic_stats_debugfs_init(struct fnic *); | ||
115 | void fnic_stats_debugfs_remove(struct fnic *); | ||
116 | #endif /* _FNIC_STATS_H_ */ | ||
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index 23a60e3d8527..e002e7187dc0 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c | |||
@@ -189,6 +189,191 @@ int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * fnic_get_stats_data - Copy fnic stats buffer to a memory file | ||
193 | * @fnic_dbgfs_t: pointer to debugfs fnic stats buffer | ||
194 | * | ||
195 | * Description: | ||
196 | * This routine gathers the fnic stats debugfs data from the fnic_stats struct | ||
197 | * and dumps it to stats_debug_info. | ||
198 | * | ||
199 | * Return Value: | ||
200 | * This routine returns the amount of bytes that were dumped into | ||
201 | * stats_debug_info | ||
202 | */ | ||
203 | int fnic_get_stats_data(struct stats_debug_info *debug, | ||
204 | struct fnic_stats *stats) | ||
205 | { | ||
206 | int len = 0; | ||
207 | int buf_size = debug->buf_size; | ||
208 | struct timespec val1, val2; | ||
209 | |||
210 | len = snprintf(debug->debug_buffer + len, buf_size - len, | ||
211 | "------------------------------------------\n" | ||
212 | "\t\tIO Statistics\n" | ||
213 | "------------------------------------------\n"); | ||
214 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
215 | "Number of Active IOs: %lld\nMaximum Active IOs: %lld\n" | ||
216 | "Number of IOs: %lld\nNumber of IO Completions: %lld\n" | ||
217 | "Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n" | ||
218 | "Number of Memory alloc Failures: %lld\n" | ||
219 | "Number of IOREQ Null: %lld\n" | ||
220 | "Number of SCSI cmd pointer Null: %lld\n", | ||
221 | (u64)atomic64_read(&stats->io_stats.active_ios), | ||
222 | (u64)atomic64_read(&stats->io_stats.max_active_ios), | ||
223 | (u64)atomic64_read(&stats->io_stats.num_ios), | ||
224 | (u64)atomic64_read(&stats->io_stats.io_completions), | ||
225 | (u64)atomic64_read(&stats->io_stats.io_failures), | ||
226 | (u64)atomic64_read(&stats->io_stats.io_not_found), | ||
227 | (u64)atomic64_read(&stats->io_stats.alloc_failures), | ||
228 | (u64)atomic64_read(&stats->io_stats.ioreq_null), | ||
229 | (u64)atomic64_read(&stats->io_stats.sc_null)); | ||
230 | |||
231 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
232 | "\n------------------------------------------\n" | ||
233 | "\t\tAbort Statistics\n" | ||
234 | "------------------------------------------\n"); | ||
235 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
236 | "Number of Aborts: %lld\n" | ||
237 | "Number of Abort Failures: %lld\n" | ||
238 | "Number of Abort Driver Timeouts: %lld\n" | ||
239 | "Number of Abort FW Timeouts: %lld\n" | ||
240 | "Number of Abort IO NOT Found: %lld\n", | ||
241 | (u64)atomic64_read(&stats->abts_stats.aborts), | ||
242 | (u64)atomic64_read(&stats->abts_stats.abort_failures), | ||
243 | (u64)atomic64_read(&stats->abts_stats.abort_drv_timeouts), | ||
244 | (u64)atomic64_read(&stats->abts_stats.abort_fw_timeouts), | ||
245 | (u64)atomic64_read(&stats->abts_stats.abort_io_not_found)); | ||
246 | |||
247 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
248 | "\n------------------------------------------\n" | ||
249 | "\t\tTerminate Statistics\n" | ||
250 | "------------------------------------------\n"); | ||
251 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
252 | "Number of Terminates: %lld\n" | ||
253 | "Maximum Terminates: %lld\n" | ||
254 | "Number of Terminate Driver Timeouts: %lld\n" | ||
255 | "Number of Terminate FW Timeouts: %lld\n" | ||
256 | "Number of Terminate IO NOT Found: %lld\n" | ||
257 | "Number of Terminate Failures: %lld\n", | ||
258 | (u64)atomic64_read(&stats->term_stats.terminates), | ||
259 | (u64)atomic64_read(&stats->term_stats.max_terminates), | ||
260 | (u64)atomic64_read(&stats->term_stats.terminate_drv_timeouts), | ||
261 | (u64)atomic64_read(&stats->term_stats.terminate_fw_timeouts), | ||
262 | (u64)atomic64_read(&stats->term_stats.terminate_io_not_found), | ||
263 | (u64)atomic64_read(&stats->term_stats.terminate_failures)); | ||
264 | |||
265 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
266 | "\n------------------------------------------\n" | ||
267 | "\t\tReset Statistics\n" | ||
268 | "------------------------------------------\n"); | ||
269 | |||
270 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
271 | "Number of Device Resets: %lld\n" | ||
272 | "Number of Device Reset Failures: %lld\n" | ||
273 | "Number of Device Reset Aborts: %lld\n" | ||
274 | "Number of Device Reset Timeouts: %lld\n" | ||
275 | "Number of Device Reset Terminates: %lld\n" | ||
276 | "Number of FW Resets: %lld\n" | ||
277 | "Number of FW Reset Completions: %lld\n" | ||
278 | "Number of FW Reset Failures: %lld\n" | ||
279 | "Number of Fnic Reset: %lld\n" | ||
280 | "Number of Fnic Reset Completions: %lld\n" | ||
281 | "Number of Fnic Reset Failures: %lld\n", | ||
282 | (u64)atomic64_read(&stats->reset_stats.device_resets), | ||
283 | (u64)atomic64_read(&stats->reset_stats.device_reset_failures), | ||
284 | (u64)atomic64_read(&stats->reset_stats.device_reset_aborts), | ||
285 | (u64)atomic64_read(&stats->reset_stats.device_reset_timeouts), | ||
286 | (u64)atomic64_read( | ||
287 | &stats->reset_stats.device_reset_terminates), | ||
288 | (u64)atomic64_read(&stats->reset_stats.fw_resets), | ||
289 | (u64)atomic64_read(&stats->reset_stats.fw_reset_completions), | ||
290 | (u64)atomic64_read(&stats->reset_stats.fw_reset_failures), | ||
291 | (u64)atomic64_read(&stats->reset_stats.fnic_resets), | ||
292 | (u64)atomic64_read( | ||
293 | &stats->reset_stats.fnic_reset_completions), | ||
294 | (u64)atomic64_read(&stats->reset_stats.fnic_reset_failures)); | ||
295 | |||
296 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
297 | "\n------------------------------------------\n" | ||
298 | "\t\tFirmware Statistics\n" | ||
299 | "------------------------------------------\n"); | ||
300 | |||
301 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
302 | "Number of Active FW Requests %lld\n" | ||
303 | "Maximum FW Requests: %lld\n" | ||
304 | "Number of FW out of resources: %lld\n" | ||
305 | "Number of FW IO errors: %lld\n", | ||
306 | (u64)atomic64_read(&stats->fw_stats.active_fw_reqs), | ||
307 | (u64)atomic64_read(&stats->fw_stats.max_fw_reqs), | ||
308 | (u64)atomic64_read(&stats->fw_stats.fw_out_of_resources), | ||
309 | (u64)atomic64_read(&stats->fw_stats.io_fw_errs)); | ||
310 | |||
311 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
312 | "\n------------------------------------------\n" | ||
313 | "\t\tVlan Discovery Statistics\n" | ||
314 | "------------------------------------------\n"); | ||
315 | |||
316 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
317 | "Number of Vlan Discovery Requests Sent %lld\n" | ||
318 | "Vlan Response Received with no FCF VLAN ID: %lld\n" | ||
319 | "No solicitations recvd after vlan set, expiry count: %lld\n" | ||
320 | "Flogi rejects count: %lld\n", | ||
321 | (u64)atomic64_read(&stats->vlan_stats.vlan_disc_reqs), | ||
322 | (u64)atomic64_read(&stats->vlan_stats.resp_withno_vlanID), | ||
323 | (u64)atomic64_read(&stats->vlan_stats.sol_expiry_count), | ||
324 | (u64)atomic64_read(&stats->vlan_stats.flogi_rejects)); | ||
325 | |||
326 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
327 | "\n------------------------------------------\n" | ||
328 | "\t\tOther Important Statistics\n" | ||
329 | "------------------------------------------\n"); | ||
330 | |||
331 | jiffies_to_timespec(stats->misc_stats.last_isr_time, &val1); | ||
332 | jiffies_to_timespec(stats->misc_stats.last_ack_time, &val2); | ||
333 | |||
334 | len += snprintf(debug->debug_buffer + len, buf_size - len, | ||
335 | "Last ISR time: %llu (%8lu.%8lu)\n" | ||
336 | "Last ACK time: %llu (%8lu.%8lu)\n" | ||
337 | "Number of ISRs: %lld\n" | ||
338 | "Maximum CQ Entries: %lld\n" | ||
339 | "Number of ACK index out of range: %lld\n" | ||
340 | "Number of data count mismatch: %lld\n" | ||
341 | "Number of FCPIO Timeouts: %lld\n" | ||
342 | "Number of FCPIO Aborted: %lld\n" | ||
343 | "Number of SGL Invalid: %lld\n" | ||
344 | "Number of Copy WQ Alloc Failures for ABTs: %lld\n" | ||
345 | "Number of Copy WQ Alloc Failures for Device Reset: %lld\n" | ||
346 | "Number of Copy WQ Alloc Failures for IOs: %lld\n" | ||
347 | "Number of no icmnd itmf Completions: %lld\n" | ||
348 | "Number of QUEUE Fulls: %lld\n" | ||
349 | "Number of rport not ready: %lld\n" | ||
350 | "Number of receive frame errors: %lld\n", | ||
351 | (u64)stats->misc_stats.last_isr_time, | ||
352 | val1.tv_sec, val1.tv_nsec, | ||
353 | (u64)stats->misc_stats.last_ack_time, | ||
354 | val2.tv_sec, val2.tv_nsec, | ||
355 | (u64)atomic64_read(&stats->misc_stats.isr_count), | ||
356 | (u64)atomic64_read(&stats->misc_stats.max_cq_entries), | ||
357 | (u64)atomic64_read(&stats->misc_stats.ack_index_out_of_range), | ||
358 | (u64)atomic64_read(&stats->misc_stats.data_count_mismatch), | ||
359 | (u64)atomic64_read(&stats->misc_stats.fcpio_timeout), | ||
360 | (u64)atomic64_read(&stats->misc_stats.fcpio_aborted), | ||
361 | (u64)atomic64_read(&stats->misc_stats.sgl_invalid), | ||
362 | (u64)atomic64_read( | ||
363 | &stats->misc_stats.abts_cpwq_alloc_failures), | ||
364 | (u64)atomic64_read( | ||
365 | &stats->misc_stats.devrst_cpwq_alloc_failures), | ||
366 | (u64)atomic64_read(&stats->misc_stats.io_cpwq_alloc_failures), | ||
367 | (u64)atomic64_read(&stats->misc_stats.no_icmnd_itmf_cmpls), | ||
368 | (u64)atomic64_read(&stats->misc_stats.queue_fulls), | ||
369 | (u64)atomic64_read(&stats->misc_stats.rport_not_ready), | ||
370 | (u64)atomic64_read(&stats->misc_stats.frame_errors)); | ||
371 | |||
372 | return len; | ||
373 | |||
374 | } | ||
375 | |||
376 | /* | ||
192 | * fnic_trace_buf_init - Initialize fnic trace buffer logging facility | 377 | * fnic_trace_buf_init - Initialize fnic trace buffer logging facility |
193 | * | 378 | * |
194 | * Description: | 379 | * Description: |
diff --git a/drivers/scsi/fnic/fnic_trace.h b/drivers/scsi/fnic/fnic_trace.h index cef42b4c4d6c..d412f2ee3c4f 100644 --- a/drivers/scsi/fnic/fnic_trace.h +++ b/drivers/scsi/fnic/fnic_trace.h | |||
@@ -84,7 +84,8 @@ fnic_trace_data_t *fnic_trace_get_buf(void); | |||
84 | int fnic_get_trace_data(fnic_dbgfs_t *); | 84 | int fnic_get_trace_data(fnic_dbgfs_t *); |
85 | int fnic_trace_buf_init(void); | 85 | int fnic_trace_buf_init(void); |
86 | void fnic_trace_free(void); | 86 | void fnic_trace_free(void); |
87 | int fnic_debugfs_init(void); | ||
88 | void fnic_debugfs_terminate(void); | ||
87 | int fnic_trace_debugfs_init(void); | 89 | int fnic_trace_debugfs_init(void); |
88 | void fnic_trace_debugfs_terminate(void); | 90 | void fnic_trace_debugfs_terminate(void); |
89 | |||
90 | #endif | 91 | #endif |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index df0c3c71ea43..f334859024c0 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -316,6 +316,12 @@ static void scsi_host_dev_release(struct device *dev) | |||
316 | kfree(shost); | 316 | kfree(shost); |
317 | } | 317 | } |
318 | 318 | ||
319 | static unsigned int shost_eh_deadline; | ||
320 | |||
321 | module_param_named(eh_deadline, shost_eh_deadline, uint, S_IRUGO|S_IWUSR); | ||
322 | MODULE_PARM_DESC(eh_deadline, | ||
323 | "SCSI EH timeout in seconds (should be between 1 and 2^32-1)"); | ||
324 | |||
319 | static struct device_type scsi_host_type = { | 325 | static struct device_type scsi_host_type = { |
320 | .name = "scsi_host", | 326 | .name = "scsi_host", |
321 | .release = scsi_host_dev_release, | 327 | .release = scsi_host_dev_release, |
@@ -388,6 +394,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
388 | shost->unchecked_isa_dma = sht->unchecked_isa_dma; | 394 | shost->unchecked_isa_dma = sht->unchecked_isa_dma; |
389 | shost->use_clustering = sht->use_clustering; | 395 | shost->use_clustering = sht->use_clustering; |
390 | shost->ordered_tag = sht->ordered_tag; | 396 | shost->ordered_tag = sht->ordered_tag; |
397 | shost->eh_deadline = shost_eh_deadline * HZ; | ||
391 | 398 | ||
392 | if (sht->supported_mode == MODE_UNKNOWN) | 399 | if (sht->supported_mode == MODE_UNKNOWN) |
393 | /* means we didn't set it ... default to INITIATOR */ | 400 | /* means we didn't set it ... default to INITIATOR */ |
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 891c86b66253..fb5a89815150 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -100,7 +100,6 @@ static const struct pci_device_id hpsa_pci_device_id[] = { | |||
100 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354}, | 100 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354}, |
101 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355}, | 101 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355}, |
102 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356}, | 102 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356}, |
103 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1920}, | ||
104 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921}, | 103 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921}, |
105 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922}, | 104 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922}, |
106 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923}, | 105 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923}, |
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 9e2588a6881c..add6d1566ec8 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -116,6 +116,7 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk) | |||
116 | struct iscsi_conn *conn = sk->sk_user_data; | 116 | struct iscsi_conn *conn = sk->sk_user_data; |
117 | 117 | ||
118 | if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) && | 118 | if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) && |
119 | (conn->session->state != ISCSI_STATE_LOGGING_OUT) && | ||
119 | !atomic_read(&sk->sk_rmem_alloc)) { | 120 | !atomic_read(&sk->sk_rmem_alloc)) { |
120 | ISCSI_SW_TCP_DBG(conn, "TCP_CLOSE|TCP_CLOSE_WAIT\n"); | 121 | ISCSI_SW_TCP_DBG(conn, "TCP_CLOSE|TCP_CLOSE_WAIT\n"); |
121 | iscsi_conn_failure(conn, ISCSI_ERR_TCP_CONN_CLOSE); | 122 | iscsi_conn_failure(conn, ISCSI_ERR_TCP_CONN_CLOSE); |
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 587992952b3c..1b3a09473452 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/export.h> | 29 | #include <linux/export.h> |
30 | #include <linux/log2.h> | ||
30 | 31 | ||
31 | #include <scsi/fc/fc_fc2.h> | 32 | #include <scsi/fc/fc_fc2.h> |
32 | 33 | ||
@@ -303,10 +304,7 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, | |||
303 | fr_eof(fp) = FC_EOF_N; | 304 | fr_eof(fp) = FC_EOF_N; |
304 | } | 305 | } |
305 | 306 | ||
306 | /* | 307 | /* Initialize remaining fh fields from fc_fill_fc_hdr */ |
307 | * Initialize remainig fh fields | ||
308 | * from fc_fill_fc_hdr | ||
309 | */ | ||
310 | fh->fh_ox_id = htons(ep->oxid); | 308 | fh->fh_ox_id = htons(ep->oxid); |
311 | fh->fh_rx_id = htons(ep->rxid); | 309 | fh->fh_rx_id = htons(ep->rxid); |
312 | fh->fh_seq_id = ep->seq.id; | 310 | fh->fh_seq_id = ep->seq.id; |
@@ -362,9 +360,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, | |||
362 | 360 | ||
363 | FC_EXCH_DBG(ep, "Exchange timer armed : %d msecs\n", timer_msec); | 361 | FC_EXCH_DBG(ep, "Exchange timer armed : %d msecs\n", timer_msec); |
364 | 362 | ||
365 | if (queue_delayed_work(fc_exch_workqueue, &ep->timeout_work, | 363 | fc_exch_hold(ep); /* hold for timer */ |
366 | msecs_to_jiffies(timer_msec))) | 364 | if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work, |
367 | fc_exch_hold(ep); /* hold for timer */ | 365 | msecs_to_jiffies(timer_msec))) |
366 | fc_exch_release(ep); | ||
368 | } | 367 | } |
369 | 368 | ||
370 | /** | 369 | /** |
@@ -382,6 +381,8 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec) | |||
382 | /** | 381 | /** |
383 | * fc_exch_done_locked() - Complete an exchange with the exchange lock held | 382 | * fc_exch_done_locked() - Complete an exchange with the exchange lock held |
384 | * @ep: The exchange that is complete | 383 | * @ep: The exchange that is complete |
384 | * | ||
385 | * Note: May sleep if invoked from outside a response handler. | ||
385 | */ | 386 | */ |
386 | static int fc_exch_done_locked(struct fc_exch *ep) | 387 | static int fc_exch_done_locked(struct fc_exch *ep) |
387 | { | 388 | { |
@@ -393,7 +394,6 @@ static int fc_exch_done_locked(struct fc_exch *ep) | |||
393 | * ep, and in that case we only clear the resp and set it as | 394 | * ep, and in that case we only clear the resp and set it as |
394 | * complete, so it can be reused by the timer to send the rrq. | 395 | * complete, so it can be reused by the timer to send the rrq. |
395 | */ | 396 | */ |
396 | ep->resp = NULL; | ||
397 | if (ep->state & FC_EX_DONE) | 397 | if (ep->state & FC_EX_DONE) |
398 | return rc; | 398 | return rc; |
399 | ep->esb_stat |= ESB_ST_COMPLETE; | 399 | ep->esb_stat |= ESB_ST_COMPLETE; |
@@ -464,15 +464,21 @@ static void fc_exch_delete(struct fc_exch *ep) | |||
464 | } | 464 | } |
465 | 465 | ||
466 | static int fc_seq_send_locked(struct fc_lport *lport, struct fc_seq *sp, | 466 | static int fc_seq_send_locked(struct fc_lport *lport, struct fc_seq *sp, |
467 | struct fc_frame *fp) | 467 | struct fc_frame *fp) |
468 | { | 468 | { |
469 | struct fc_exch *ep; | 469 | struct fc_exch *ep; |
470 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 470 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
471 | int error; | 471 | int error = -ENXIO; |
472 | u32 f_ctl; | 472 | u32 f_ctl; |
473 | u8 fh_type = fh->fh_type; | 473 | u8 fh_type = fh->fh_type; |
474 | 474 | ||
475 | ep = fc_seq_exch(sp); | 475 | ep = fc_seq_exch(sp); |
476 | |||
477 | if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL)) { | ||
478 | fc_frame_free(fp); | ||
479 | goto out; | ||
480 | } | ||
481 | |||
476 | WARN_ON(!(ep->esb_stat & ESB_ST_SEQ_INIT)); | 482 | WARN_ON(!(ep->esb_stat & ESB_ST_SEQ_INIT)); |
477 | 483 | ||
478 | f_ctl = ntoh24(fh->fh_f_ctl); | 484 | f_ctl = ntoh24(fh->fh_f_ctl); |
@@ -515,6 +521,9 @@ out: | |||
515 | * @lport: The local port that the exchange will be sent on | 521 | * @lport: The local port that the exchange will be sent on |
516 | * @sp: The sequence to be sent | 522 | * @sp: The sequence to be sent |
517 | * @fp: The frame to be sent on the exchange | 523 | * @fp: The frame to be sent on the exchange |
524 | * | ||
525 | * Note: The frame will be freed either by a direct call to fc_frame_free(fp) | ||
526 | * or indirectly by calling libfc_function_template.frame_send(). | ||
518 | */ | 527 | */ |
519 | static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, | 528 | static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, |
520 | struct fc_frame *fp) | 529 | struct fc_frame *fp) |
@@ -581,6 +590,8 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) | |||
581 | 590 | ||
582 | /* | 591 | /* |
583 | * Set the response handler for the exchange associated with a sequence. | 592 | * Set the response handler for the exchange associated with a sequence. |
593 | * | ||
594 | * Note: May sleep if invoked from outside a response handler. | ||
584 | */ | 595 | */ |
585 | static void fc_seq_set_resp(struct fc_seq *sp, | 596 | static void fc_seq_set_resp(struct fc_seq *sp, |
586 | void (*resp)(struct fc_seq *, struct fc_frame *, | 597 | void (*resp)(struct fc_seq *, struct fc_frame *, |
@@ -588,8 +599,18 @@ static void fc_seq_set_resp(struct fc_seq *sp, | |||
588 | void *arg) | 599 | void *arg) |
589 | { | 600 | { |
590 | struct fc_exch *ep = fc_seq_exch(sp); | 601 | struct fc_exch *ep = fc_seq_exch(sp); |
602 | DEFINE_WAIT(wait); | ||
591 | 603 | ||
592 | spin_lock_bh(&ep->ex_lock); | 604 | spin_lock_bh(&ep->ex_lock); |
605 | while (ep->resp_active && ep->resp_task != current) { | ||
606 | prepare_to_wait(&ep->resp_wq, &wait, TASK_UNINTERRUPTIBLE); | ||
607 | spin_unlock_bh(&ep->ex_lock); | ||
608 | |||
609 | schedule(); | ||
610 | |||
611 | spin_lock_bh(&ep->ex_lock); | ||
612 | } | ||
613 | finish_wait(&ep->resp_wq, &wait); | ||
593 | ep->resp = resp; | 614 | ep->resp = resp; |
594 | ep->arg = arg; | 615 | ep->arg = arg; |
595 | spin_unlock_bh(&ep->ex_lock); | 616 | spin_unlock_bh(&ep->ex_lock); |
@@ -622,27 +643,31 @@ static int fc_exch_abort_locked(struct fc_exch *ep, | |||
622 | if (!sp) | 643 | if (!sp) |
623 | return -ENOMEM; | 644 | return -ENOMEM; |
624 | 645 | ||
625 | ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL; | ||
626 | if (timer_msec) | 646 | if (timer_msec) |
627 | fc_exch_timer_set_locked(ep, timer_msec); | 647 | fc_exch_timer_set_locked(ep, timer_msec); |
628 | 648 | ||
629 | /* | 649 | if (ep->sid) { |
630 | * If not logged into the fabric, don't send ABTS but leave | 650 | /* |
631 | * sequence active until next timeout. | 651 | * Send an abort for the sequence that timed out. |
632 | */ | 652 | */ |
633 | if (!ep->sid) | 653 | fp = fc_frame_alloc(ep->lp, 0); |
634 | return 0; | 654 | if (fp) { |
635 | 655 | ep->esb_stat |= ESB_ST_SEQ_INIT; | |
636 | /* | 656 | fc_fill_fc_hdr(fp, FC_RCTL_BA_ABTS, ep->did, ep->sid, |
637 | * Send an abort for the sequence that timed out. | 657 | FC_TYPE_BLS, FC_FC_END_SEQ | |
638 | */ | 658 | FC_FC_SEQ_INIT, 0); |
639 | fp = fc_frame_alloc(ep->lp, 0); | 659 | error = fc_seq_send_locked(ep->lp, sp, fp); |
640 | if (fp) { | 660 | } else { |
641 | fc_fill_fc_hdr(fp, FC_RCTL_BA_ABTS, ep->did, ep->sid, | 661 | error = -ENOBUFS; |
642 | FC_TYPE_BLS, FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 662 | } |
643 | error = fc_seq_send_locked(ep->lp, sp, fp); | 663 | } else { |
644 | } else | 664 | /* |
645 | error = -ENOBUFS; | 665 | * If not logged into the fabric, don't send ABTS but leave |
666 | * sequence active until next timeout. | ||
667 | */ | ||
668 | error = 0; | ||
669 | } | ||
670 | ep->esb_stat |= ESB_ST_ABNORMAL; | ||
646 | return error; | 671 | return error; |
647 | } | 672 | } |
648 | 673 | ||
@@ -669,6 +694,61 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp, | |||
669 | } | 694 | } |
670 | 695 | ||
671 | /** | 696 | /** |
697 | * fc_invoke_resp() - invoke ep->resp() | ||
698 | * | ||
699 | * Notes: | ||
700 | * It is assumed that after initialization finished (this means the | ||
701 | * first unlock of ex_lock after fc_exch_alloc()) ep->resp and ep->arg are | ||
702 | * modified only via fc_seq_set_resp(). This guarantees that none of these | ||
703 | * two variables changes if ep->resp_active > 0. | ||
704 | * | ||
705 | * If an fc_seq_set_resp() call is busy modifying ep->resp and ep->arg when | ||
706 | * this function is invoked, the first spin_lock_bh() call in this function | ||
707 | * will wait until fc_seq_set_resp() has finished modifying these variables. | ||
708 | * | ||
709 | * Since fc_exch_done() invokes fc_seq_set_resp() it is guaranteed that that | ||
710 | * ep->resp() won't be invoked after fc_exch_done() has returned. | ||
711 | * | ||
712 | * The response handler itself may invoke fc_exch_done(), which will clear the | ||
713 | * ep->resp pointer. | ||
714 | * | ||
715 | * Return value: | ||
716 | * Returns true if and only if ep->resp has been invoked. | ||
717 | */ | ||
718 | static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp, | ||
719 | struct fc_frame *fp) | ||
720 | { | ||
721 | void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); | ||
722 | void *arg; | ||
723 | bool res = false; | ||
724 | |||
725 | spin_lock_bh(&ep->ex_lock); | ||
726 | ep->resp_active++; | ||
727 | if (ep->resp_task != current) | ||
728 | ep->resp_task = !ep->resp_task ? current : NULL; | ||
729 | resp = ep->resp; | ||
730 | arg = ep->arg; | ||
731 | spin_unlock_bh(&ep->ex_lock); | ||
732 | |||
733 | if (resp) { | ||
734 | resp(sp, fp, arg); | ||
735 | res = true; | ||
736 | } else if (!IS_ERR(fp)) { | ||
737 | fc_frame_free(fp); | ||
738 | } | ||
739 | |||
740 | spin_lock_bh(&ep->ex_lock); | ||
741 | if (--ep->resp_active == 0) | ||
742 | ep->resp_task = NULL; | ||
743 | spin_unlock_bh(&ep->ex_lock); | ||
744 | |||
745 | if (ep->resp_active == 0) | ||
746 | wake_up(&ep->resp_wq); | ||
747 | |||
748 | return res; | ||
749 | } | ||
750 | |||
751 | /** | ||
672 | * fc_exch_timeout() - Handle exchange timer expiration | 752 | * fc_exch_timeout() - Handle exchange timer expiration |
673 | * @work: The work_struct identifying the exchange that timed out | 753 | * @work: The work_struct identifying the exchange that timed out |
674 | */ | 754 | */ |
@@ -677,8 +757,6 @@ static void fc_exch_timeout(struct work_struct *work) | |||
677 | struct fc_exch *ep = container_of(work, struct fc_exch, | 757 | struct fc_exch *ep = container_of(work, struct fc_exch, |
678 | timeout_work.work); | 758 | timeout_work.work); |
679 | struct fc_seq *sp = &ep->seq; | 759 | struct fc_seq *sp = &ep->seq; |
680 | void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); | ||
681 | void *arg; | ||
682 | u32 e_stat; | 760 | u32 e_stat; |
683 | int rc = 1; | 761 | int rc = 1; |
684 | 762 | ||
@@ -696,16 +774,13 @@ static void fc_exch_timeout(struct work_struct *work) | |||
696 | fc_exch_rrq(ep); | 774 | fc_exch_rrq(ep); |
697 | goto done; | 775 | goto done; |
698 | } else { | 776 | } else { |
699 | resp = ep->resp; | ||
700 | arg = ep->arg; | ||
701 | ep->resp = NULL; | ||
702 | if (e_stat & ESB_ST_ABNORMAL) | 777 | if (e_stat & ESB_ST_ABNORMAL) |
703 | rc = fc_exch_done_locked(ep); | 778 | rc = fc_exch_done_locked(ep); |
704 | spin_unlock_bh(&ep->ex_lock); | 779 | spin_unlock_bh(&ep->ex_lock); |
705 | if (!rc) | 780 | if (!rc) |
706 | fc_exch_delete(ep); | 781 | fc_exch_delete(ep); |
707 | if (resp) | 782 | fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_TIMEOUT)); |
708 | resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg); | 783 | fc_seq_set_resp(sp, NULL, ep->arg); |
709 | fc_seq_exch_abort(sp, 2 * ep->r_a_tov); | 784 | fc_seq_exch_abort(sp, 2 * ep->r_a_tov); |
710 | goto done; | 785 | goto done; |
711 | } | 786 | } |
@@ -792,6 +867,8 @@ hit: | |||
792 | ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */ | 867 | ep->f_ctl = FC_FC_FIRST_SEQ; /* next seq is first seq */ |
793 | ep->rxid = FC_XID_UNKNOWN; | 868 | ep->rxid = FC_XID_UNKNOWN; |
794 | ep->class = mp->class; | 869 | ep->class = mp->class; |
870 | ep->resp_active = 0; | ||
871 | init_waitqueue_head(&ep->resp_wq); | ||
795 | INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout); | 872 | INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout); |
796 | out: | 873 | out: |
797 | return ep; | 874 | return ep; |
@@ -838,8 +915,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) | |||
838 | pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask); | 915 | pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask); |
839 | spin_lock_bh(&pool->lock); | 916 | spin_lock_bh(&pool->lock); |
840 | ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order); | 917 | ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order); |
841 | if (ep && ep->xid == xid) | 918 | if (ep) { |
919 | WARN_ON(ep->xid != xid); | ||
842 | fc_exch_hold(ep); | 920 | fc_exch_hold(ep); |
921 | } | ||
843 | spin_unlock_bh(&pool->lock); | 922 | spin_unlock_bh(&pool->lock); |
844 | } | 923 | } |
845 | return ep; | 924 | return ep; |
@@ -850,6 +929,8 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) | |||
850 | * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and | 929 | * fc_exch_done() - Indicate that an exchange/sequence tuple is complete and |
851 | * the memory allocated for the related objects may be freed. | 930 | * the memory allocated for the related objects may be freed. |
852 | * @sp: The sequence that has completed | 931 | * @sp: The sequence that has completed |
932 | * | ||
933 | * Note: May sleep if invoked from outside a response handler. | ||
853 | */ | 934 | */ |
854 | static void fc_exch_done(struct fc_seq *sp) | 935 | static void fc_exch_done(struct fc_seq *sp) |
855 | { | 936 | { |
@@ -859,6 +940,8 @@ static void fc_exch_done(struct fc_seq *sp) | |||
859 | spin_lock_bh(&ep->ex_lock); | 940 | spin_lock_bh(&ep->ex_lock); |
860 | rc = fc_exch_done_locked(ep); | 941 | rc = fc_exch_done_locked(ep); |
861 | spin_unlock_bh(&ep->ex_lock); | 942 | spin_unlock_bh(&ep->ex_lock); |
943 | |||
944 | fc_seq_set_resp(sp, NULL, ep->arg); | ||
862 | if (!rc) | 945 | if (!rc) |
863 | fc_exch_delete(ep); | 946 | fc_exch_delete(ep); |
864 | } | 947 | } |
@@ -987,6 +1070,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, | |||
987 | } | 1070 | } |
988 | } | 1071 | } |
989 | 1072 | ||
1073 | spin_lock_bh(&ep->ex_lock); | ||
990 | /* | 1074 | /* |
991 | * At this point, we have the exchange held. | 1075 | * At this point, we have the exchange held. |
992 | * Find or create the sequence. | 1076 | * Find or create the sequence. |
@@ -1014,11 +1098,11 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, | |||
1014 | * sending RSP, hence write request on other | 1098 | * sending RSP, hence write request on other |
1015 | * end never finishes. | 1099 | * end never finishes. |
1016 | */ | 1100 | */ |
1017 | spin_lock_bh(&ep->ex_lock); | ||
1018 | sp->ssb_stat |= SSB_ST_RESP; | 1101 | sp->ssb_stat |= SSB_ST_RESP; |
1019 | sp->id = fh->fh_seq_id; | 1102 | sp->id = fh->fh_seq_id; |
1020 | spin_unlock_bh(&ep->ex_lock); | ||
1021 | } else { | 1103 | } else { |
1104 | spin_unlock_bh(&ep->ex_lock); | ||
1105 | |||
1022 | /* sequence/exch should exist */ | 1106 | /* sequence/exch should exist */ |
1023 | reject = FC_RJT_SEQ_ID; | 1107 | reject = FC_RJT_SEQ_ID; |
1024 | goto rel; | 1108 | goto rel; |
@@ -1029,6 +1113,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, | |||
1029 | 1113 | ||
1030 | if (f_ctl & FC_FC_SEQ_INIT) | 1114 | if (f_ctl & FC_FC_SEQ_INIT) |
1031 | ep->esb_stat |= ESB_ST_SEQ_INIT; | 1115 | ep->esb_stat |= ESB_ST_SEQ_INIT; |
1116 | spin_unlock_bh(&ep->ex_lock); | ||
1032 | 1117 | ||
1033 | fr_seq(fp) = sp; | 1118 | fr_seq(fp) = sp; |
1034 | out: | 1119 | out: |
@@ -1291,21 +1376,23 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) | |||
1291 | 1376 | ||
1292 | if (!ep) | 1377 | if (!ep) |
1293 | goto reject; | 1378 | goto reject; |
1379 | |||
1380 | fp = fc_frame_alloc(ep->lp, sizeof(*ap)); | ||
1381 | if (!fp) | ||
1382 | goto free; | ||
1383 | |||
1294 | spin_lock_bh(&ep->ex_lock); | 1384 | spin_lock_bh(&ep->ex_lock); |
1295 | if (ep->esb_stat & ESB_ST_COMPLETE) { | 1385 | if (ep->esb_stat & ESB_ST_COMPLETE) { |
1296 | spin_unlock_bh(&ep->ex_lock); | 1386 | spin_unlock_bh(&ep->ex_lock); |
1387 | |||
1388 | fc_frame_free(fp); | ||
1297 | goto reject; | 1389 | goto reject; |
1298 | } | 1390 | } |
1299 | if (!(ep->esb_stat & ESB_ST_REC_QUAL)) | 1391 | if (!(ep->esb_stat & ESB_ST_REC_QUAL)) { |
1392 | ep->esb_stat |= ESB_ST_REC_QUAL; | ||
1300 | fc_exch_hold(ep); /* hold for REC_QUAL */ | 1393 | fc_exch_hold(ep); /* hold for REC_QUAL */ |
1301 | ep->esb_stat |= ESB_ST_ABNORMAL | ESB_ST_REC_QUAL; | ||
1302 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | ||
1303 | |||
1304 | fp = fc_frame_alloc(ep->lp, sizeof(*ap)); | ||
1305 | if (!fp) { | ||
1306 | spin_unlock_bh(&ep->ex_lock); | ||
1307 | goto free; | ||
1308 | } | 1394 | } |
1395 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | ||
1309 | fh = fc_frame_header_get(fp); | 1396 | fh = fc_frame_header_get(fp); |
1310 | ap = fc_frame_payload_get(fp, sizeof(*ap)); | 1397 | ap = fc_frame_payload_get(fp, sizeof(*ap)); |
1311 | memset(ap, 0, sizeof(*ap)); | 1398 | memset(ap, 0, sizeof(*ap)); |
@@ -1319,14 +1406,16 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) | |||
1319 | } | 1406 | } |
1320 | sp = fc_seq_start_next_locked(sp); | 1407 | sp = fc_seq_start_next_locked(sp); |
1321 | fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); | 1408 | fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); |
1409 | ep->esb_stat |= ESB_ST_ABNORMAL; | ||
1322 | spin_unlock_bh(&ep->ex_lock); | 1410 | spin_unlock_bh(&ep->ex_lock); |
1411 | |||
1412 | free: | ||
1323 | fc_frame_free(rx_fp); | 1413 | fc_frame_free(rx_fp); |
1324 | return; | 1414 | return; |
1325 | 1415 | ||
1326 | reject: | 1416 | reject: |
1327 | fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID); | 1417 | fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID); |
1328 | free: | 1418 | goto free; |
1329 | fc_frame_free(rx_fp); | ||
1330 | } | 1419 | } |
1331 | 1420 | ||
1332 | /** | 1421 | /** |
@@ -1416,9 +1505,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, | |||
1416 | * If new exch resp handler is valid then call that | 1505 | * If new exch resp handler is valid then call that |
1417 | * first. | 1506 | * first. |
1418 | */ | 1507 | */ |
1419 | if (ep->resp) | 1508 | if (!fc_invoke_resp(ep, sp, fp)) |
1420 | ep->resp(sp, fp, ep->arg); | ||
1421 | else | ||
1422 | lport->tt.lport_recv(lport, fp); | 1509 | lport->tt.lport_recv(lport, fp); |
1423 | fc_exch_release(ep); /* release from lookup */ | 1510 | fc_exch_release(ep); /* release from lookup */ |
1424 | } else { | 1511 | } else { |
@@ -1442,8 +1529,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1442 | struct fc_exch *ep; | 1529 | struct fc_exch *ep; |
1443 | enum fc_sof sof; | 1530 | enum fc_sof sof; |
1444 | u32 f_ctl; | 1531 | u32 f_ctl; |
1445 | void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); | ||
1446 | void *ex_resp_arg; | ||
1447 | int rc; | 1532 | int rc; |
1448 | 1533 | ||
1449 | ep = fc_exch_find(mp, ntohs(fh->fh_ox_id)); | 1534 | ep = fc_exch_find(mp, ntohs(fh->fh_ox_id)); |
@@ -1478,19 +1563,19 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1478 | 1563 | ||
1479 | f_ctl = ntoh24(fh->fh_f_ctl); | 1564 | f_ctl = ntoh24(fh->fh_f_ctl); |
1480 | fr_seq(fp) = sp; | 1565 | fr_seq(fp) = sp; |
1566 | |||
1567 | spin_lock_bh(&ep->ex_lock); | ||
1481 | if (f_ctl & FC_FC_SEQ_INIT) | 1568 | if (f_ctl & FC_FC_SEQ_INIT) |
1482 | ep->esb_stat |= ESB_ST_SEQ_INIT; | 1569 | ep->esb_stat |= ESB_ST_SEQ_INIT; |
1570 | spin_unlock_bh(&ep->ex_lock); | ||
1483 | 1571 | ||
1484 | if (fc_sof_needs_ack(sof)) | 1572 | if (fc_sof_needs_ack(sof)) |
1485 | fc_seq_send_ack(sp, fp); | 1573 | fc_seq_send_ack(sp, fp); |
1486 | resp = ep->resp; | ||
1487 | ex_resp_arg = ep->arg; | ||
1488 | 1574 | ||
1489 | if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T && | 1575 | if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T && |
1490 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == | 1576 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == |
1491 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { | 1577 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { |
1492 | spin_lock_bh(&ep->ex_lock); | 1578 | spin_lock_bh(&ep->ex_lock); |
1493 | resp = ep->resp; | ||
1494 | rc = fc_exch_done_locked(ep); | 1579 | rc = fc_exch_done_locked(ep); |
1495 | WARN_ON(fc_seq_exch(sp) != ep); | 1580 | WARN_ON(fc_seq_exch(sp) != ep); |
1496 | spin_unlock_bh(&ep->ex_lock); | 1581 | spin_unlock_bh(&ep->ex_lock); |
@@ -1511,10 +1596,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1511 | * If new exch resp handler is valid then call that | 1596 | * If new exch resp handler is valid then call that |
1512 | * first. | 1597 | * first. |
1513 | */ | 1598 | */ |
1514 | if (resp) | 1599 | fc_invoke_resp(ep, sp, fp); |
1515 | resp(sp, fp, ex_resp_arg); | 1600 | |
1516 | else | ||
1517 | fc_frame_free(fp); | ||
1518 | fc_exch_release(ep); | 1601 | fc_exch_release(ep); |
1519 | return; | 1602 | return; |
1520 | rel: | 1603 | rel: |
@@ -1553,8 +1636,6 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1553 | */ | 1636 | */ |
1554 | static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) | 1637 | static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) |
1555 | { | 1638 | { |
1556 | void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg); | ||
1557 | void *ex_resp_arg; | ||
1558 | struct fc_frame_header *fh; | 1639 | struct fc_frame_header *fh; |
1559 | struct fc_ba_acc *ap; | 1640 | struct fc_ba_acc *ap; |
1560 | struct fc_seq *sp; | 1641 | struct fc_seq *sp; |
@@ -1599,9 +1680,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) | |||
1599 | break; | 1680 | break; |
1600 | } | 1681 | } |
1601 | 1682 | ||
1602 | resp = ep->resp; | ||
1603 | ex_resp_arg = ep->arg; | ||
1604 | |||
1605 | /* do we need to do some other checks here. Can we reuse more of | 1683 | /* do we need to do some other checks here. Can we reuse more of |
1606 | * fc_exch_recv_seq_resp | 1684 | * fc_exch_recv_seq_resp |
1607 | */ | 1685 | */ |
@@ -1613,17 +1691,14 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) | |||
1613 | ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ) | 1691 | ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ) |
1614 | rc = fc_exch_done_locked(ep); | 1692 | rc = fc_exch_done_locked(ep); |
1615 | spin_unlock_bh(&ep->ex_lock); | 1693 | spin_unlock_bh(&ep->ex_lock); |
1694 | |||
1695 | fc_exch_hold(ep); | ||
1616 | if (!rc) | 1696 | if (!rc) |
1617 | fc_exch_delete(ep); | 1697 | fc_exch_delete(ep); |
1618 | 1698 | fc_invoke_resp(ep, sp, fp); | |
1619 | if (resp) | ||
1620 | resp(sp, fp, ex_resp_arg); | ||
1621 | else | ||
1622 | fc_frame_free(fp); | ||
1623 | |||
1624 | if (has_rec) | 1699 | if (has_rec) |
1625 | fc_exch_timer_set(ep, ep->r_a_tov); | 1700 | fc_exch_timer_set(ep, ep->r_a_tov); |
1626 | 1701 | fc_exch_release(ep); | |
1627 | } | 1702 | } |
1628 | 1703 | ||
1629 | /** | 1704 | /** |
@@ -1662,7 +1737,7 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1662 | break; | 1737 | break; |
1663 | default: | 1738 | default: |
1664 | if (ep) | 1739 | if (ep) |
1665 | FC_EXCH_DBG(ep, "BLS rctl %x - %s received", | 1740 | FC_EXCH_DBG(ep, "BLS rctl %x - %s received\n", |
1666 | fh->fh_r_ctl, | 1741 | fh->fh_r_ctl, |
1667 | fc_exch_rctl_name(fh->fh_r_ctl)); | 1742 | fc_exch_rctl_name(fh->fh_r_ctl)); |
1668 | break; | 1743 | break; |
@@ -1745,32 +1820,33 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, | |||
1745 | /** | 1820 | /** |
1746 | * fc_exch_reset() - Reset an exchange | 1821 | * fc_exch_reset() - Reset an exchange |
1747 | * @ep: The exchange to be reset | 1822 | * @ep: The exchange to be reset |
1823 | * | ||
1824 | * Note: May sleep if invoked from outside a response handler. | ||
1748 | */ | 1825 | */ |
1749 | static void fc_exch_reset(struct fc_exch *ep) | 1826 | static void fc_exch_reset(struct fc_exch *ep) |
1750 | { | 1827 | { |
1751 | struct fc_seq *sp; | 1828 | struct fc_seq *sp; |
1752 | void (*resp)(struct fc_seq *, struct fc_frame *, void *); | ||
1753 | void *arg; | ||
1754 | int rc = 1; | 1829 | int rc = 1; |
1755 | 1830 | ||
1756 | spin_lock_bh(&ep->ex_lock); | 1831 | spin_lock_bh(&ep->ex_lock); |
1757 | fc_exch_abort_locked(ep, 0); | 1832 | fc_exch_abort_locked(ep, 0); |
1758 | ep->state |= FC_EX_RST_CLEANUP; | 1833 | ep->state |= FC_EX_RST_CLEANUP; |
1759 | fc_exch_timer_cancel(ep); | 1834 | fc_exch_timer_cancel(ep); |
1760 | resp = ep->resp; | ||
1761 | ep->resp = NULL; | ||
1762 | if (ep->esb_stat & ESB_ST_REC_QUAL) | 1835 | if (ep->esb_stat & ESB_ST_REC_QUAL) |
1763 | atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */ | 1836 | atomic_dec(&ep->ex_refcnt); /* drop hold for rec_qual */ |
1764 | ep->esb_stat &= ~ESB_ST_REC_QUAL; | 1837 | ep->esb_stat &= ~ESB_ST_REC_QUAL; |
1765 | arg = ep->arg; | ||
1766 | sp = &ep->seq; | 1838 | sp = &ep->seq; |
1767 | rc = fc_exch_done_locked(ep); | 1839 | rc = fc_exch_done_locked(ep); |
1768 | spin_unlock_bh(&ep->ex_lock); | 1840 | spin_unlock_bh(&ep->ex_lock); |
1841 | |||
1842 | fc_exch_hold(ep); | ||
1843 | |||
1769 | if (!rc) | 1844 | if (!rc) |
1770 | fc_exch_delete(ep); | 1845 | fc_exch_delete(ep); |
1771 | 1846 | ||
1772 | if (resp) | 1847 | fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED)); |
1773 | resp(sp, ERR_PTR(-FC_EX_CLOSED), arg); | 1848 | fc_seq_set_resp(sp, NULL, ep->arg); |
1849 | fc_exch_release(ep); | ||
1774 | } | 1850 | } |
1775 | 1851 | ||
1776 | /** | 1852 | /** |
@@ -1956,13 +2032,13 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) | |||
1956 | 2032 | ||
1957 | switch (op) { | 2033 | switch (op) { |
1958 | case ELS_LS_RJT: | 2034 | case ELS_LS_RJT: |
1959 | FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ"); | 2035 | FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ\n"); |
1960 | /* fall through */ | 2036 | /* fall through */ |
1961 | case ELS_LS_ACC: | 2037 | case ELS_LS_ACC: |
1962 | goto cleanup; | 2038 | goto cleanup; |
1963 | default: | 2039 | default: |
1964 | FC_EXCH_DBG(aborted_ep, "unexpected response op %x " | 2040 | FC_EXCH_DBG(aborted_ep, "unexpected response op %x for RRQ\n", |
1965 | "for RRQ", op); | 2041 | op); |
1966 | return; | 2042 | return; |
1967 | } | 2043 | } |
1968 | 2044 | ||
@@ -2533,13 +2609,8 @@ int fc_setup_exch_mgr(void) | |||
2533 | * cpu on which exchange originated by simple bitwise | 2609 | * cpu on which exchange originated by simple bitwise |
2534 | * AND operation between fc_cpu_mask and exchange id. | 2610 | * AND operation between fc_cpu_mask and exchange id. |
2535 | */ | 2611 | */ |
2536 | fc_cpu_mask = 1; | 2612 | fc_cpu_order = ilog2(roundup_pow_of_two(nr_cpu_ids)); |
2537 | fc_cpu_order = 0; | 2613 | fc_cpu_mask = (1 << fc_cpu_order) - 1; |
2538 | while (fc_cpu_mask < nr_cpu_ids) { | ||
2539 | fc_cpu_mask <<= 1; | ||
2540 | fc_cpu_order++; | ||
2541 | } | ||
2542 | fc_cpu_mask--; | ||
2543 | 2614 | ||
2544 | fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue"); | 2615 | fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue"); |
2545 | if (!fc_exch_workqueue) | 2616 | if (!fc_exch_workqueue) |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5fd0f1fbe586..1d7e76e8b447 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -902,7 +902,8 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
902 | /* | 902 | /* |
903 | * Check for missing or extra data frames. | 903 | * Check for missing or extra data frames. |
904 | */ | 904 | */ |
905 | if (unlikely(fsp->xfer_len != expected_len)) { | 905 | if (unlikely(fsp->cdb_status == SAM_STAT_GOOD && |
906 | fsp->xfer_len != expected_len)) { | ||
906 | if (fsp->xfer_len < expected_len) { | 907 | if (fsp->xfer_len < expected_len) { |
907 | /* | 908 | /* |
908 | * Some data may be queued locally, | 909 | * Some data may be queued locally, |
@@ -955,12 +956,11 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) | |||
955 | * Test for transport underrun, independent of response | 956 | * Test for transport underrun, independent of response |
956 | * underrun status. | 957 | * underrun status. |
957 | */ | 958 | */ |
958 | if (fsp->xfer_len < fsp->data_len && !fsp->io_status && | 959 | if (fsp->cdb_status == SAM_STAT_GOOD && |
960 | fsp->xfer_len < fsp->data_len && !fsp->io_status && | ||
959 | (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || | 961 | (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || |
960 | fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { | 962 | fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) |
961 | fsp->status_code = FC_DATA_UNDRUN; | 963 | fsp->status_code = FC_DATA_UNDRUN; |
962 | fsp->io_status = 0; | ||
963 | } | ||
964 | } | 964 | } |
965 | 965 | ||
966 | seq = fsp->seq_ptr; | 966 | seq = fsp->seq_ptr; |
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index f04d15c67df3..e01a29863c38 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -516,7 +516,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, | |||
516 | * @lport: The local port receiving the LOGO | 516 | * @lport: The local port receiving the LOGO |
517 | * @fp: The LOGO request frame | 517 | * @fp: The LOGO request frame |
518 | * | 518 | * |
519 | * Locking Note: The lport lock is exected to be held before calling | 519 | * Locking Note: The lport lock is expected to be held before calling |
520 | * this function. | 520 | * this function. |
521 | */ | 521 | */ |
522 | static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) | 522 | static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) |
@@ -1088,7 +1088,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) | |||
1088 | { | 1088 | { |
1089 | unsigned long delay = 0; | 1089 | unsigned long delay = 0; |
1090 | FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n", | 1090 | FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n", |
1091 | PTR_ERR(fp), fc_lport_state(lport), | 1091 | IS_ERR(fp) ? -PTR_ERR(fp) : 0, fc_lport_state(lport), |
1092 | lport->retry_count); | 1092 | lport->retry_count); |
1093 | 1093 | ||
1094 | if (PTR_ERR(fp) == -FC_EX_CLOSED) | 1094 | if (PTR_ERR(fp) == -FC_EX_CLOSED) |
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c710d908fda6..589ff9aedd31 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -1705,7 +1705,7 @@ reject: | |||
1705 | * @rdata: The remote port that sent the PRLI request | 1705 | * @rdata: The remote port that sent the PRLI request |
1706 | * @rx_fp: The PRLI request frame | 1706 | * @rx_fp: The PRLI request frame |
1707 | * | 1707 | * |
1708 | * Locking Note: The rport lock is exected to be held before calling | 1708 | * Locking Note: The rport lock is expected to be held before calling |
1709 | * this function. | 1709 | * this function. |
1710 | */ | 1710 | */ |
1711 | static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | 1711 | static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, |
@@ -1824,7 +1824,7 @@ drop: | |||
1824 | * @rdata: The remote port that sent the PRLO request | 1824 | * @rdata: The remote port that sent the PRLO request |
1825 | * @rx_fp: The PRLO request frame | 1825 | * @rx_fp: The PRLO request frame |
1826 | * | 1826 | * |
1827 | * Locking Note: The rport lock is exected to be held before calling | 1827 | * Locking Note: The rport lock is expected to be held before calling |
1828 | * this function. | 1828 | * this function. |
1829 | */ | 1829 | */ |
1830 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | 1830 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, |
@@ -1895,7 +1895,7 @@ drop: | |||
1895 | * @lport: The local port that received the LOGO request | 1895 | * @lport: The local port that received the LOGO request |
1896 | * @fp: The LOGO request frame | 1896 | * @fp: The LOGO request frame |
1897 | * | 1897 | * |
1898 | * Locking Note: The rport lock is exected to be held before calling | 1898 | * Locking Note: The rport lock is expected to be held before calling |
1899 | * this function. | 1899 | * this function. |
1900 | */ | 1900 | */ |
1901 | static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) | 1901 | static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index b92aec989d60..82134d20e2d8 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -2629,7 +2629,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, | |||
2629 | rspiocbq, | 2629 | rspiocbq, |
2630 | (phba->fc_ratov * 2) | 2630 | (phba->fc_ratov * 2) |
2631 | + LPFC_DRVR_TIMEOUT); | 2631 | + LPFC_DRVR_TIMEOUT); |
2632 | if (iocb_stat) { | 2632 | if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOSTAT_SUCCESS)) { |
2633 | ret_val = -EIO; | 2633 | ret_val = -EIO; |
2634 | goto err_get_xri_exit; | 2634 | goto err_get_xri_exit; |
2635 | } | 2635 | } |
@@ -3204,8 +3204,9 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
3204 | rspiocbq, (phba->fc_ratov * 2) + | 3204 | rspiocbq, (phba->fc_ratov * 2) + |
3205 | LPFC_DRVR_TIMEOUT); | 3205 | LPFC_DRVR_TIMEOUT); |
3206 | 3206 | ||
3207 | if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) && | 3207 | if ((iocb_stat != IOCB_SUCCESS) || |
3208 | (rsp->ulpStatus != IOCB_SUCCESS))) { | 3208 | ((phba->sli_rev < LPFC_SLI_REV4) && |
3209 | (rsp->ulpStatus != IOSTAT_SUCCESS))) { | ||
3209 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | 3210 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, |
3210 | "3126 Failed loopback test issue iocb: " | 3211 | "3126 Failed loopback test issue iocb: " |
3211 | "iocb_stat:x%x\n", iocb_stat); | 3212 | "iocb_stat:x%x\n", iocb_stat); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 02e8cd923d0a..da61d8dc0449 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -280,7 +280,7 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) | |||
280 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3; | 280 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3; |
281 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | 281 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); |
282 | kfree(buf_ptr); | 282 | kfree(buf_ptr); |
283 | ctiocb->context1 = NULL; | 283 | ctiocb->context3 = NULL; |
284 | } | 284 | } |
285 | lpfc_sli_release_iocbq(phba, ctiocb); | 285 | lpfc_sli_release_iocbq(phba, ctiocb); |
286 | return 0; | 286 | return 0; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7801601aa5d9..883ea2d9f237 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -4171,8 +4171,6 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4171 | NLP_INT_NODE_ACT(ndlp); | 4171 | NLP_INT_NODE_ACT(ndlp); |
4172 | atomic_set(&ndlp->cmd_pending, 0); | 4172 | atomic_set(&ndlp->cmd_pending, 0); |
4173 | ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; | 4173 | ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; |
4174 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | ||
4175 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | ||
4176 | } | 4174 | } |
4177 | 4175 | ||
4178 | struct lpfc_nodelist * | 4176 | struct lpfc_nodelist * |
@@ -4217,6 +4215,9 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4217 | lpfc_initialize_node(vport, ndlp, did); | 4215 | lpfc_initialize_node(vport, ndlp, did); |
4218 | 4216 | ||
4219 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); | 4217 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); |
4218 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | ||
4219 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | ||
4220 | |||
4220 | 4221 | ||
4221 | if (state != NLP_STE_UNUSED_NODE) | 4222 | if (state != NLP_STE_UNUSED_NODE) |
4222 | lpfc_nlp_set_state(vport, ndlp, state); | 4223 | lpfc_nlp_set_state(vport, ndlp, state); |
@@ -5617,6 +5618,9 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
5617 | 5618 | ||
5618 | lpfc_initialize_node(vport, ndlp, did); | 5619 | lpfc_initialize_node(vport, ndlp, did); |
5619 | INIT_LIST_HEAD(&ndlp->nlp_listp); | 5620 | INIT_LIST_HEAD(&ndlp->nlp_listp); |
5621 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | ||
5622 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | ||
5623 | |||
5620 | 5624 | ||
5621 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | 5625 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, |
5622 | "node init: did:x%x", | 5626 | "node init: did:x%x", |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 086c3f28caa6..5464b116d328 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -3439,7 +3439,8 @@ struct els_request64_wqe { | |||
3439 | #define els_req64_hopcnt_SHIFT 24 | 3439 | #define els_req64_hopcnt_SHIFT 24 |
3440 | #define els_req64_hopcnt_MASK 0x000000ff | 3440 | #define els_req64_hopcnt_MASK 0x000000ff |
3441 | #define els_req64_hopcnt_WORD word13 | 3441 | #define els_req64_hopcnt_WORD word13 |
3442 | uint32_t reserved[2]; | 3442 | uint32_t word14; |
3443 | uint32_t max_response_payload_len; | ||
3443 | }; | 3444 | }; |
3444 | 3445 | ||
3445 | struct xmit_els_rsp64_wqe { | 3446 | struct xmit_els_rsp64_wqe { |
@@ -3554,7 +3555,8 @@ struct gen_req64_wqe { | |||
3554 | uint32_t relative_offset; | 3555 | uint32_t relative_offset; |
3555 | struct wqe_rctl_dfctl wge_ctl; /* word 5 */ | 3556 | struct wqe_rctl_dfctl wge_ctl; /* word 5 */ |
3556 | struct wqe_common wqe_com; /* words 6-11 */ | 3557 | struct wqe_common wqe_com; /* words 6-11 */ |
3557 | uint32_t rsvd_12_15[4]; | 3558 | uint32_t rsvd_12_14[3]; |
3559 | uint32_t max_response_payload_len; | ||
3558 | }; | 3560 | }; |
3559 | 3561 | ||
3560 | struct create_xri_wqe { | 3562 | struct create_xri_wqe { |
@@ -3584,7 +3586,13 @@ struct abort_cmd_wqe { | |||
3584 | 3586 | ||
3585 | struct fcp_iwrite64_wqe { | 3587 | struct fcp_iwrite64_wqe { |
3586 | struct ulp_bde64 bde; | 3588 | struct ulp_bde64 bde; |
3587 | uint32_t payload_offset_len; | 3589 | uint32_t word3; |
3590 | #define cmd_buff_len_SHIFT 16 | ||
3591 | #define cmd_buff_len_MASK 0x00000ffff | ||
3592 | #define cmd_buff_len_WORD word3 | ||
3593 | #define payload_offset_len_SHIFT 0 | ||
3594 | #define payload_offset_len_MASK 0x0000ffff | ||
3595 | #define payload_offset_len_WORD word3 | ||
3588 | uint32_t total_xfer_len; | 3596 | uint32_t total_xfer_len; |
3589 | uint32_t initial_xfer_len; | 3597 | uint32_t initial_xfer_len; |
3590 | struct wqe_common wqe_com; /* words 6-11 */ | 3598 | struct wqe_common wqe_com; /* words 6-11 */ |
@@ -3594,7 +3602,13 @@ struct fcp_iwrite64_wqe { | |||
3594 | 3602 | ||
3595 | struct fcp_iread64_wqe { | 3603 | struct fcp_iread64_wqe { |
3596 | struct ulp_bde64 bde; | 3604 | struct ulp_bde64 bde; |
3597 | uint32_t payload_offset_len; /* word 3 */ | 3605 | uint32_t word3; |
3606 | #define cmd_buff_len_SHIFT 16 | ||
3607 | #define cmd_buff_len_MASK 0x00000ffff | ||
3608 | #define cmd_buff_len_WORD word3 | ||
3609 | #define payload_offset_len_SHIFT 0 | ||
3610 | #define payload_offset_len_MASK 0x0000ffff | ||
3611 | #define payload_offset_len_WORD word3 | ||
3598 | uint32_t total_xfer_len; /* word 4 */ | 3612 | uint32_t total_xfer_len; /* word 4 */ |
3599 | uint32_t rsrvd5; /* word 5 */ | 3613 | uint32_t rsrvd5; /* word 5 */ |
3600 | struct wqe_common wqe_com; /* words 6-11 */ | 3614 | struct wqe_common wqe_com; /* words 6-11 */ |
@@ -3604,7 +3618,13 @@ struct fcp_iread64_wqe { | |||
3604 | 3618 | ||
3605 | struct fcp_icmnd64_wqe { | 3619 | struct fcp_icmnd64_wqe { |
3606 | struct ulp_bde64 bde; /* words 0-2 */ | 3620 | struct ulp_bde64 bde; /* words 0-2 */ |
3607 | uint32_t rsrvd3; /* word 3 */ | 3621 | uint32_t word3; |
3622 | #define cmd_buff_len_SHIFT 16 | ||
3623 | #define cmd_buff_len_MASK 0x00000ffff | ||
3624 | #define cmd_buff_len_WORD word3 | ||
3625 | #define payload_offset_len_SHIFT 0 | ||
3626 | #define payload_offset_len_MASK 0x0000ffff | ||
3627 | #define payload_offset_len_WORD word3 | ||
3608 | uint32_t rsrvd4; /* word 4 */ | 3628 | uint32_t rsrvd4; /* word 4 */ |
3609 | uint32_t rsrvd5; /* word 5 */ | 3629 | uint32_t rsrvd5; /* word 5 */ |
3610 | struct wqe_common wqe_com; /* words 6-11 */ | 3630 | struct wqe_common wqe_com; /* words 6-11 */ |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 647f5bfb3bd3..ca6bf2af7ce8 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -4545,7 +4545,7 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba) | |||
4545 | pci_save_state(pdev); | 4545 | pci_save_state(pdev); |
4546 | 4546 | ||
4547 | /* PCIe EEH recovery on powerpc platforms needs fundamental reset */ | 4547 | /* PCIe EEH recovery on powerpc platforms needs fundamental reset */ |
4548 | if (pci_find_capability(pdev, PCI_CAP_ID_EXP)) | 4548 | if (pci_is_pcie(pdev)) |
4549 | pdev->needs_freset = 1; | 4549 | pdev->needs_freset = 1; |
4550 | 4550 | ||
4551 | return 0; | 4551 | return 0; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c913e8cc3b26..b2ede05a5f0a 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1012,20 +1012,25 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
1012 | break; | 1012 | break; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | /* Allocate iotag for psb->cur_iocbq. */ | 1015 | |
1016 | iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); | 1016 | lxri = lpfc_sli4_next_xritag(phba); |
1017 | if (iotag == 0) { | 1017 | if (lxri == NO_XRI) { |
1018 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | 1018 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, |
1019 | psb->data, psb->dma_handle); | 1019 | psb->data, psb->dma_handle); |
1020 | kfree(psb); | 1020 | kfree(psb); |
1021 | break; | 1021 | break; |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | lxri = lpfc_sli4_next_xritag(phba); | 1024 | /* Allocate iotag for psb->cur_iocbq. */ |
1025 | if (lxri == NO_XRI) { | 1025 | iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); |
1026 | if (iotag == 0) { | ||
1026 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | 1027 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, |
1027 | psb->data, psb->dma_handle); | 1028 | psb->data, psb->dma_handle); |
1028 | kfree(psb); | 1029 | kfree(psb); |
1030 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
1031 | "3368 Failed to allocated IOTAG for" | ||
1032 | " XRI:0x%x\n", lxri); | ||
1033 | lpfc_sli4_free_xri(phba, lxri); | ||
1029 | break; | 1034 | break; |
1030 | } | 1035 | } |
1031 | psb->cur_iocbq.sli4_lxritag = lxri; | 1036 | psb->cur_iocbq.sli4_lxritag = lxri; |
@@ -4485,9 +4490,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, | |||
4485 | piocb->ulpContext = | 4490 | piocb->ulpContext = |
4486 | vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | 4491 | vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
4487 | } | 4492 | } |
4488 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { | 4493 | piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0; |
4489 | piocb->ulpFCP2Rcvy = 1; | ||
4490 | } | ||
4491 | piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); | 4494 | piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); |
4492 | 4495 | ||
4493 | /* ulpTimeout is only one byte */ | 4496 | /* ulpTimeout is only one byte */ |
@@ -4981,6 +4984,73 @@ lpfc_taskmgmt_name(uint8_t task_mgmt_cmd) | |||
4981 | } | 4984 | } |
4982 | } | 4985 | } |
4983 | 4986 | ||
4987 | |||
4988 | /** | ||
4989 | * lpfc_check_fcp_rsp - check the returned fcp_rsp to see if task failed | ||
4990 | * @vport: The virtual port for which this call is being executed. | ||
4991 | * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. | ||
4992 | * | ||
4993 | * This routine checks the FCP RSP INFO to see if the tsk mgmt command succeded | ||
4994 | * | ||
4995 | * Return code : | ||
4996 | * 0x2003 - Error | ||
4997 | * 0x2002 - Success | ||
4998 | **/ | ||
4999 | static int | ||
5000 | lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd) | ||
5001 | { | ||
5002 | struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; | ||
5003 | uint32_t rsp_info; | ||
5004 | uint32_t rsp_len; | ||
5005 | uint8_t rsp_info_code; | ||
5006 | int ret = FAILED; | ||
5007 | |||
5008 | |||
5009 | if (fcprsp == NULL) | ||
5010 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
5011 | "0703 fcp_rsp is missing\n"); | ||
5012 | else { | ||
5013 | rsp_info = fcprsp->rspStatus2; | ||
5014 | rsp_len = be32_to_cpu(fcprsp->rspRspLen); | ||
5015 | rsp_info_code = fcprsp->rspInfo3; | ||
5016 | |||
5017 | |||
5018 | lpfc_printf_vlog(vport, KERN_INFO, | ||
5019 | LOG_FCP, | ||
5020 | "0706 fcp_rsp valid 0x%x," | ||
5021 | " rsp len=%d code 0x%x\n", | ||
5022 | rsp_info, | ||
5023 | rsp_len, rsp_info_code); | ||
5024 | |||
5025 | if ((fcprsp->rspStatus2&RSP_LEN_VALID) && (rsp_len == 8)) { | ||
5026 | switch (rsp_info_code) { | ||
5027 | case RSP_NO_FAILURE: | ||
5028 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
5029 | "0715 Task Mgmt No Failure\n"); | ||
5030 | ret = SUCCESS; | ||
5031 | break; | ||
5032 | case RSP_TM_NOT_SUPPORTED: /* TM rejected */ | ||
5033 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
5034 | "0716 Task Mgmt Target " | ||
5035 | "reject\n"); | ||
5036 | break; | ||
5037 | case RSP_TM_NOT_COMPLETED: /* TM failed */ | ||
5038 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
5039 | "0717 Task Mgmt Target " | ||
5040 | "failed TM\n"); | ||
5041 | break; | ||
5042 | case RSP_TM_INVALID_LU: /* TM to invalid LU! */ | ||
5043 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
5044 | "0718 Task Mgmt to invalid " | ||
5045 | "LUN\n"); | ||
5046 | break; | ||
5047 | } | ||
5048 | } | ||
5049 | } | ||
5050 | return ret; | ||
5051 | } | ||
5052 | |||
5053 | |||
4984 | /** | 5054 | /** |
4985 | * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler | 5055 | * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler |
4986 | * @vport: The virtual port for which this call is being executed. | 5056 | * @vport: The virtual port for which this call is being executed. |
@@ -5042,12 +5112,8 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
5042 | 5112 | ||
5043 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, | 5113 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, |
5044 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 5114 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
5045 | if (status != IOCB_SUCCESS) { | 5115 | if ((status != IOCB_SUCCESS) || |
5046 | if (status == IOCB_TIMEDOUT) { | 5116 | (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { |
5047 | ret = TIMEOUT_ERROR; | ||
5048 | } else | ||
5049 | ret = FAILED; | ||
5050 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | ||
5051 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 5117 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
5052 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " | 5118 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " |
5053 | "iocb_flag x%x\n", | 5119 | "iocb_flag x%x\n", |
@@ -5055,9 +5121,21 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
5055 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, | 5121 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, |
5056 | iocbqrsp->iocb.un.ulpWord[4], | 5122 | iocbqrsp->iocb.un.ulpWord[4], |
5057 | iocbq->iocb_flag); | 5123 | iocbq->iocb_flag); |
5058 | } else if (status == IOCB_BUSY) | 5124 | /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ |
5059 | ret = FAILED; | 5125 | if (status == IOCB_SUCCESS) { |
5060 | else | 5126 | if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) |
5127 | /* Something in the FCP_RSP was invalid. | ||
5128 | * Check conditions */ | ||
5129 | ret = lpfc_check_fcp_rsp(vport, lpfc_cmd); | ||
5130 | else | ||
5131 | ret = FAILED; | ||
5132 | } else if (status == IOCB_TIMEDOUT) { | ||
5133 | ret = TIMEOUT_ERROR; | ||
5134 | } else { | ||
5135 | ret = FAILED; | ||
5136 | } | ||
5137 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | ||
5138 | } else | ||
5061 | ret = SUCCESS; | 5139 | ret = SUCCESS; |
5062 | 5140 | ||
5063 | lpfc_sli_release_iocbq(phba, iocbqrsp); | 5141 | lpfc_sli_release_iocbq(phba, iocbqrsp); |
@@ -5181,7 +5259,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
5181 | unsigned tgt_id = cmnd->device->id; | 5259 | unsigned tgt_id = cmnd->device->id; |
5182 | unsigned int lun_id = cmnd->device->lun; | 5260 | unsigned int lun_id = cmnd->device->lun; |
5183 | struct lpfc_scsi_event_header scsi_event; | 5261 | struct lpfc_scsi_event_header scsi_event; |
5184 | int status, ret = SUCCESS; | 5262 | int status; |
5185 | 5263 | ||
5186 | if (!rdata) { | 5264 | if (!rdata) { |
5187 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 5265 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
@@ -5222,9 +5300,11 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
5222 | * So, continue on. | 5300 | * So, continue on. |
5223 | * We will report success if all the i/o aborts successfully. | 5301 | * We will report success if all the i/o aborts successfully. |
5224 | */ | 5302 | */ |
5225 | ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, | 5303 | if (status == SUCCESS) |
5304 | status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, | ||
5226 | LPFC_CTX_LUN); | 5305 | LPFC_CTX_LUN); |
5227 | return ret; | 5306 | |
5307 | return status; | ||
5228 | } | 5308 | } |
5229 | 5309 | ||
5230 | /** | 5310 | /** |
@@ -5248,7 +5328,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) | |||
5248 | unsigned tgt_id = cmnd->device->id; | 5328 | unsigned tgt_id = cmnd->device->id; |
5249 | unsigned int lun_id = cmnd->device->lun; | 5329 | unsigned int lun_id = cmnd->device->lun; |
5250 | struct lpfc_scsi_event_header scsi_event; | 5330 | struct lpfc_scsi_event_header scsi_event; |
5251 | int status, ret = SUCCESS; | 5331 | int status; |
5252 | 5332 | ||
5253 | if (!rdata) { | 5333 | if (!rdata) { |
5254 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 5334 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
@@ -5289,9 +5369,10 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) | |||
5289 | * So, continue on. | 5369 | * So, continue on. |
5290 | * We will report success if all the i/o aborts successfully. | 5370 | * We will report success if all the i/o aborts successfully. |
5291 | */ | 5371 | */ |
5292 | ret = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, | 5372 | if (status == SUCCESS) |
5373 | status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id, | ||
5293 | LPFC_CTX_TGT); | 5374 | LPFC_CTX_TGT); |
5294 | return ret; | 5375 | return status; |
5295 | } | 5376 | } |
5296 | 5377 | ||
5297 | /** | 5378 | /** |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index b1d9f7fcb911..852ff7def493 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h | |||
@@ -73,6 +73,7 @@ struct fcp_rsp { | |||
73 | #define RSP_RO_MISMATCH_ERR 0x03 | 73 | #define RSP_RO_MISMATCH_ERR 0x03 |
74 | #define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */ | 74 | #define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */ |
75 | #define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */ | 75 | #define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */ |
76 | #define RSP_TM_INVALID_LU 0x09 /* Task mgmt function to invalid LU */ | ||
76 | 77 | ||
77 | uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */ | 78 | uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */ |
78 | 79 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 612f48973ff2..8f580fda443f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -71,6 +71,8 @@ static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, | |||
71 | int); | 71 | int); |
72 | static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, | 72 | static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, |
73 | uint32_t); | 73 | uint32_t); |
74 | static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); | ||
75 | static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); | ||
74 | 76 | ||
75 | static IOCB_t * | 77 | static IOCB_t * |
76 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 78 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
@@ -6566,6 +6568,108 @@ lpfc_mbox_timeout(unsigned long ptr) | |||
6566 | return; | 6568 | return; |
6567 | } | 6569 | } |
6568 | 6570 | ||
6571 | /** | ||
6572 | * lpfc_sli4_mbox_completions_pending - check to see if any mailbox completions | ||
6573 | * are pending | ||
6574 | * @phba: Pointer to HBA context object. | ||
6575 | * | ||
6576 | * This function checks if any mailbox completions are present on the mailbox | ||
6577 | * completion queue. | ||
6578 | **/ | ||
6579 | bool | ||
6580 | lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) | ||
6581 | { | ||
6582 | |||
6583 | uint32_t idx; | ||
6584 | struct lpfc_queue *mcq; | ||
6585 | struct lpfc_mcqe *mcqe; | ||
6586 | bool pending_completions = false; | ||
6587 | |||
6588 | if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) | ||
6589 | return false; | ||
6590 | |||
6591 | /* Check for completions on mailbox completion queue */ | ||
6592 | |||
6593 | mcq = phba->sli4_hba.mbx_cq; | ||
6594 | idx = mcq->hba_index; | ||
6595 | while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe)) { | ||
6596 | mcqe = (struct lpfc_mcqe *)mcq->qe[idx].cqe; | ||
6597 | if (bf_get_le32(lpfc_trailer_completed, mcqe) && | ||
6598 | (!bf_get_le32(lpfc_trailer_async, mcqe))) { | ||
6599 | pending_completions = true; | ||
6600 | break; | ||
6601 | } | ||
6602 | idx = (idx + 1) % mcq->entry_count; | ||
6603 | if (mcq->hba_index == idx) | ||
6604 | break; | ||
6605 | } | ||
6606 | return pending_completions; | ||
6607 | |||
6608 | } | ||
6609 | |||
6610 | /** | ||
6611 | * lpfc_sli4_process_missed_mbox_completions - process mbox completions | ||
6612 | * that were missed. | ||
6613 | * @phba: Pointer to HBA context object. | ||
6614 | * | ||
6615 | * For sli4, it is possible to miss an interrupt. As such mbox completions | ||
6616 | * maybe missed causing erroneous mailbox timeouts to occur. This function | ||
6617 | * checks to see if mbox completions are on the mailbox completion queue | ||
6618 | * and will process all the completions associated with the eq for the | ||
6619 | * mailbox completion queue. | ||
6620 | **/ | ||
6621 | bool | ||
6622 | lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) | ||
6623 | { | ||
6624 | |||
6625 | uint32_t eqidx; | ||
6626 | struct lpfc_queue *fpeq = NULL; | ||
6627 | struct lpfc_eqe *eqe; | ||
6628 | bool mbox_pending; | ||
6629 | |||
6630 | if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) | ||
6631 | return false; | ||
6632 | |||
6633 | /* Find the eq associated with the mcq */ | ||
6634 | |||
6635 | if (phba->sli4_hba.hba_eq) | ||
6636 | for (eqidx = 0; eqidx < phba->cfg_fcp_io_channel; eqidx++) | ||
6637 | if (phba->sli4_hba.hba_eq[eqidx]->queue_id == | ||
6638 | phba->sli4_hba.mbx_cq->assoc_qid) { | ||
6639 | fpeq = phba->sli4_hba.hba_eq[eqidx]; | ||
6640 | break; | ||
6641 | } | ||
6642 | if (!fpeq) | ||
6643 | return false; | ||
6644 | |||
6645 | /* Turn off interrupts from this EQ */ | ||
6646 | |||
6647 | lpfc_sli4_eq_clr_intr(fpeq); | ||
6648 | |||
6649 | /* Check to see if a mbox completion is pending */ | ||
6650 | |||
6651 | mbox_pending = lpfc_sli4_mbox_completions_pending(phba); | ||
6652 | |||
6653 | /* | ||
6654 | * If a mbox completion is pending, process all the events on EQ | ||
6655 | * associated with the mbox completion queue (this could include | ||
6656 | * mailbox commands, async events, els commands, receive queue data | ||
6657 | * and fcp commands) | ||
6658 | */ | ||
6659 | |||
6660 | if (mbox_pending) | ||
6661 | while ((eqe = lpfc_sli4_eq_get(fpeq))) { | ||
6662 | lpfc_sli4_hba_handle_eqe(phba, eqe, eqidx); | ||
6663 | fpeq->EQ_processed++; | ||
6664 | } | ||
6665 | |||
6666 | /* Always clear and re-arm the EQ */ | ||
6667 | |||
6668 | lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); | ||
6669 | |||
6670 | return mbox_pending; | ||
6671 | |||
6672 | } | ||
6569 | 6673 | ||
6570 | /** | 6674 | /** |
6571 | * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout | 6675 | * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout |
@@ -6583,6 +6687,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
6583 | struct lpfc_sli *psli = &phba->sli; | 6687 | struct lpfc_sli *psli = &phba->sli; |
6584 | struct lpfc_sli_ring *pring; | 6688 | struct lpfc_sli_ring *pring; |
6585 | 6689 | ||
6690 | /* If the mailbox completed, process the completion and return */ | ||
6691 | if (lpfc_sli4_process_missed_mbox_completions(phba)) | ||
6692 | return; | ||
6693 | |||
6586 | /* Check the pmbox pointer first. There is a race condition | 6694 | /* Check the pmbox pointer first. There is a race condition |
6587 | * between the mbox timeout handler getting executed in the | 6695 | * between the mbox timeout handler getting executed in the |
6588 | * worklist and the mailbox actually completing. When this | 6696 | * worklist and the mailbox actually completing. When this |
@@ -7077,6 +7185,10 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) | |||
7077 | 1000) + jiffies; | 7185 | 1000) + jiffies; |
7078 | spin_unlock_irq(&phba->hbalock); | 7186 | spin_unlock_irq(&phba->hbalock); |
7079 | 7187 | ||
7188 | /* Make sure the mailbox is really active */ | ||
7189 | if (timeout) | ||
7190 | lpfc_sli4_process_missed_mbox_completions(phba); | ||
7191 | |||
7080 | /* Wait for the outstnading mailbox command to complete */ | 7192 | /* Wait for the outstnading mailbox command to complete */ |
7081 | while (phba->sli.mbox_active) { | 7193 | while (phba->sli.mbox_active) { |
7082 | /* Check active mailbox complete status every 2ms */ | 7194 | /* Check active mailbox complete status every 2ms */ |
@@ -8076,6 +8188,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8076 | bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); | 8188 | bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); |
8077 | bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); | 8189 | bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); |
8078 | bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); | 8190 | bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); |
8191 | wqe->els_req.max_response_payload_len = total_len - xmit_len; | ||
8079 | break; | 8192 | break; |
8080 | case CMD_XMIT_SEQUENCE64_CX: | 8193 | case CMD_XMIT_SEQUENCE64_CX: |
8081 | bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, | 8194 | bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, |
@@ -8120,8 +8233,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8120 | command_type = FCP_COMMAND_DATA_OUT; | 8233 | command_type = FCP_COMMAND_DATA_OUT; |
8121 | /* word3 iocb=iotag wqe=payload_offset_len */ | 8234 | /* word3 iocb=iotag wqe=payload_offset_len */ |
8122 | /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ | 8235 | /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ |
8123 | wqe->fcp_iwrite.payload_offset_len = | 8236 | bf_set(payload_offset_len, &wqe->fcp_iwrite, |
8124 | xmit_len + sizeof(struct fcp_rsp); | 8237 | xmit_len + sizeof(struct fcp_rsp)); |
8238 | bf_set(cmd_buff_len, &wqe->fcp_iwrite, | ||
8239 | 0); | ||
8125 | /* word4 iocb=parameter wqe=total_xfer_length memcpy */ | 8240 | /* word4 iocb=parameter wqe=total_xfer_length memcpy */ |
8126 | /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ | 8241 | /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ |
8127 | bf_set(wqe_erp, &wqe->fcp_iwrite.wqe_com, | 8242 | bf_set(wqe_erp, &wqe->fcp_iwrite.wqe_com, |
@@ -8139,8 +8254,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8139 | case CMD_FCP_IREAD64_CR: | 8254 | case CMD_FCP_IREAD64_CR: |
8140 | /* word3 iocb=iotag wqe=payload_offset_len */ | 8255 | /* word3 iocb=iotag wqe=payload_offset_len */ |
8141 | /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ | 8256 | /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ |
8142 | wqe->fcp_iread.payload_offset_len = | 8257 | bf_set(payload_offset_len, &wqe->fcp_iread, |
8143 | xmit_len + sizeof(struct fcp_rsp); | 8258 | xmit_len + sizeof(struct fcp_rsp)); |
8259 | bf_set(cmd_buff_len, &wqe->fcp_iread, | ||
8260 | 0); | ||
8144 | /* word4 iocb=parameter wqe=total_xfer_length memcpy */ | 8261 | /* word4 iocb=parameter wqe=total_xfer_length memcpy */ |
8145 | /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ | 8262 | /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ |
8146 | bf_set(wqe_erp, &wqe->fcp_iread.wqe_com, | 8263 | bf_set(wqe_erp, &wqe->fcp_iread.wqe_com, |
@@ -8156,8 +8273,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8156 | bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); | 8273 | bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); |
8157 | break; | 8274 | break; |
8158 | case CMD_FCP_ICMND64_CR: | 8275 | case CMD_FCP_ICMND64_CR: |
8276 | /* word3 iocb=iotag wqe=payload_offset_len */ | ||
8277 | /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ | ||
8278 | bf_set(payload_offset_len, &wqe->fcp_icmd, | ||
8279 | xmit_len + sizeof(struct fcp_rsp)); | ||
8280 | bf_set(cmd_buff_len, &wqe->fcp_icmd, | ||
8281 | 0); | ||
8159 | /* word3 iocb=IO_TAG wqe=reserved */ | 8282 | /* word3 iocb=IO_TAG wqe=reserved */ |
8160 | wqe->fcp_icmd.rsrvd3 = 0; | ||
8161 | bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); | 8283 | bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); |
8162 | /* Always open the exchange */ | 8284 | /* Always open the exchange */ |
8163 | bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); | 8285 | bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); |
@@ -8203,6 +8325,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8203 | bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); | 8325 | bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); |
8204 | bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); | 8326 | bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); |
8205 | bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); | 8327 | bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); |
8328 | wqe->gen_req.max_response_payload_len = total_len - xmit_len; | ||
8206 | command_type = OTHER_COMMAND; | 8329 | command_type = OTHER_COMMAND; |
8207 | break; | 8330 | break; |
8208 | case CMD_XMIT_ELS_RSP64_CX: | 8331 | case CMD_XMIT_ELS_RSP64_CX: |
@@ -10073,6 +10196,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
10073 | if (iocb_completed) { | 10196 | if (iocb_completed) { |
10074 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 10197 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
10075 | "0331 IOCB wake signaled\n"); | 10198 | "0331 IOCB wake signaled\n"); |
10199 | /* Note: we are not indicating if the IOCB has a success | ||
10200 | * status or not - that's for the caller to check. | ||
10201 | * IOCB_SUCCESS means just that the command was sent and | ||
10202 | * completed. Not that it completed successfully. | ||
10203 | * */ | ||
10076 | } else if (timeleft == 0) { | 10204 | } else if (timeleft == 0) { |
10077 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 10205 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
10078 | "0338 IOCB wait timeout error - no " | 10206 | "0338 IOCB wait timeout error - no " |
@@ -11074,8 +11202,11 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, | |||
11074 | struct lpfc_iocbq *pIocbOut, | 11202 | struct lpfc_iocbq *pIocbOut, |
11075 | struct lpfc_wcqe_complete *wcqe) | 11203 | struct lpfc_wcqe_complete *wcqe) |
11076 | { | 11204 | { |
11205 | int numBdes, i; | ||
11077 | unsigned long iflags; | 11206 | unsigned long iflags; |
11078 | uint32_t status; | 11207 | uint32_t status, max_response; |
11208 | struct lpfc_dmabuf *dmabuf; | ||
11209 | struct ulp_bde64 *bpl, bde; | ||
11079 | size_t offset = offsetof(struct lpfc_iocbq, iocb); | 11210 | size_t offset = offsetof(struct lpfc_iocbq, iocb); |
11080 | 11211 | ||
11081 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, | 11212 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, |
@@ -11092,7 +11223,36 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, | |||
11092 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 11223 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
11093 | else { | 11224 | else { |
11094 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 11225 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
11095 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = wcqe->total_data_placed; | 11226 | switch (pIocbOut->iocb.ulpCommand) { |
11227 | case CMD_ELS_REQUEST64_CR: | ||
11228 | dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; | ||
11229 | bpl = (struct ulp_bde64 *)dmabuf->virt; | ||
11230 | bde.tus.w = le32_to_cpu(bpl[1].tus.w); | ||
11231 | max_response = bde.tus.f.bdeSize; | ||
11232 | break; | ||
11233 | case CMD_GEN_REQUEST64_CR: | ||
11234 | max_response = 0; | ||
11235 | if (!pIocbOut->context3) | ||
11236 | break; | ||
11237 | numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/ | ||
11238 | sizeof(struct ulp_bde64); | ||
11239 | dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; | ||
11240 | bpl = (struct ulp_bde64 *)dmabuf->virt; | ||
11241 | for (i = 0; i < numBdes; i++) { | ||
11242 | bde.tus.w = le32_to_cpu(bpl[i].tus.w); | ||
11243 | if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) | ||
11244 | max_response += bde.tus.f.bdeSize; | ||
11245 | } | ||
11246 | break; | ||
11247 | default: | ||
11248 | max_response = wcqe->total_data_placed; | ||
11249 | break; | ||
11250 | } | ||
11251 | if (max_response < wcqe->total_data_placed) | ||
11252 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response; | ||
11253 | else | ||
11254 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = | ||
11255 | wcqe->total_data_placed; | ||
11096 | } | 11256 | } |
11097 | 11257 | ||
11098 | /* Convert BG errors for completion status */ | 11258 | /* Convert BG errors for completion status */ |
@@ -15098,6 +15258,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15098 | uint16_t max_rpi, rpi_limit; | 15258 | uint16_t max_rpi, rpi_limit; |
15099 | uint16_t rpi_remaining, lrpi = 0; | 15259 | uint16_t rpi_remaining, lrpi = 0; |
15100 | struct lpfc_rpi_hdr *rpi_hdr; | 15260 | struct lpfc_rpi_hdr *rpi_hdr; |
15261 | unsigned long iflag; | ||
15101 | 15262 | ||
15102 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | 15263 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; |
15103 | rpi_limit = phba->sli4_hba.next_rpi; | 15264 | rpi_limit = phba->sli4_hba.next_rpi; |
@@ -15106,7 +15267,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15106 | * Fetch the next logical rpi. Because this index is logical, | 15267 | * Fetch the next logical rpi. Because this index is logical, |
15107 | * the driver starts at 0 each time. | 15268 | * the driver starts at 0 each time. |
15108 | */ | 15269 | */ |
15109 | spin_lock_irq(&phba->hbalock); | 15270 | spin_lock_irqsave(&phba->hbalock, iflag); |
15110 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); | 15271 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); |
15111 | if (rpi >= rpi_limit) | 15272 | if (rpi >= rpi_limit) |
15112 | rpi = LPFC_RPI_ALLOC_ERROR; | 15273 | rpi = LPFC_RPI_ALLOC_ERROR; |
@@ -15122,7 +15283,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15122 | */ | 15283 | */ |
15123 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && | 15284 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && |
15124 | (phba->sli4_hba.rpi_count >= max_rpi)) { | 15285 | (phba->sli4_hba.rpi_count >= max_rpi)) { |
15125 | spin_unlock_irq(&phba->hbalock); | 15286 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
15126 | return rpi; | 15287 | return rpi; |
15127 | } | 15288 | } |
15128 | 15289 | ||
@@ -15131,7 +15292,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15131 | * extents. | 15292 | * extents. |
15132 | */ | 15293 | */ |
15133 | if (!phba->sli4_hba.rpi_hdrs_in_use) { | 15294 | if (!phba->sli4_hba.rpi_hdrs_in_use) { |
15134 | spin_unlock_irq(&phba->hbalock); | 15295 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
15135 | return rpi; | 15296 | return rpi; |
15136 | } | 15297 | } |
15137 | 15298 | ||
@@ -15142,7 +15303,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15142 | * how many are supported max by the device. | 15303 | * how many are supported max by the device. |
15143 | */ | 15304 | */ |
15144 | rpi_remaining = phba->sli4_hba.next_rpi - phba->sli4_hba.rpi_count; | 15305 | rpi_remaining = phba->sli4_hba.next_rpi - phba->sli4_hba.rpi_count; |
15145 | spin_unlock_irq(&phba->hbalock); | 15306 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
15146 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { | 15307 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { |
15147 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | 15308 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); |
15148 | if (!rpi_hdr) { | 15309 | if (!rpi_hdr) { |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 85120b77aa0e..298c8cd1a89d 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -673,6 +673,7 @@ void lpfc_sli4_queue_unset(struct lpfc_hba *); | |||
673 | int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t); | 673 | int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t); |
674 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); | 674 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); |
675 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); | 675 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); |
676 | void lpfc_sli4_free_xri(struct lpfc_hba *, int); | ||
676 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); | 677 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); |
677 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); | 678 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); |
678 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); | 679 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index f58f18342bc3..e3094c4e143b 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.3.42" | 21 | #define LPFC_DRIVER_VERSION "8.3.43" |
22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
23 | 23 | ||
24 | /* Used for SLI 2/3 */ | 24 | /* Used for SLI 2/3 */ |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 0c73ba4bf451..e9e543c58485 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -1531,6 +1531,7 @@ struct megasas_instance { | |||
1531 | struct megasas_register_set __iomem *reg_set; | 1531 | struct megasas_register_set __iomem *reg_set; |
1532 | u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY]; | 1532 | u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY]; |
1533 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; | 1533 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; |
1534 | struct megasas_pd_list local_pd_list[MEGASAS_MAX_PD]; | ||
1534 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; | 1535 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; |
1535 | s8 init_id; | 1536 | s8 init_id; |
1536 | 1537 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 3020921a4746..2cf9470dd11b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -3194,19 +3194,21 @@ megasas_get_pd_list(struct megasas_instance *instance) | |||
3194 | (le32_to_cpu(ci->count) < | 3194 | (le32_to_cpu(ci->count) < |
3195 | (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { | 3195 | (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { |
3196 | 3196 | ||
3197 | memset(instance->pd_list, 0, | 3197 | memset(instance->local_pd_list, 0, |
3198 | MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); | 3198 | MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); |
3199 | 3199 | ||
3200 | for (pd_index = 0; pd_index < le32_to_cpu(ci->count); pd_index++) { | 3200 | for (pd_index = 0; pd_index < le32_to_cpu(ci->count); pd_index++) { |
3201 | 3201 | ||
3202 | instance->pd_list[pd_addr->deviceId].tid = | 3202 | instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].tid = |
3203 | le16_to_cpu(pd_addr->deviceId); | 3203 | le16_to_cpu(pd_addr->deviceId); |
3204 | instance->pd_list[pd_addr->deviceId].driveType = | 3204 | instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].driveType = |
3205 | pd_addr->scsiDevType; | 3205 | pd_addr->scsiDevType; |
3206 | instance->pd_list[pd_addr->deviceId].driveState = | 3206 | instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].driveState = |
3207 | MR_PD_STATE_SYSTEM; | 3207 | MR_PD_STATE_SYSTEM; |
3208 | pd_addr++; | 3208 | pd_addr++; |
3209 | } | 3209 | } |
3210 | memcpy(instance->pd_list, instance->local_pd_list, | ||
3211 | sizeof(instance->pd_list)); | ||
3210 | } | 3212 | } |
3211 | 3213 | ||
3212 | pci_free_consistent(instance->pdev, | 3214 | pci_free_consistent(instance->pdev, |
@@ -3998,7 +4000,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
3998 | * values | 4000 | * values |
3999 | */ | 4001 | */ |
4000 | if ((prev_aen.members.class <= curr_aen.members.class) && | 4002 | if ((prev_aen.members.class <= curr_aen.members.class) && |
4001 | !((le16_to_cpu(prev_aen.members.locale) & curr_aen.members.locale) ^ | 4003 | !((prev_aen.members.locale & curr_aen.members.locale) ^ |
4002 | curr_aen.members.locale)) { | 4004 | curr_aen.members.locale)) { |
4003 | /* | 4005 | /* |
4004 | * Previously issued event registration includes | 4006 | * Previously issued event registration includes |
@@ -4006,7 +4008,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
4006 | */ | 4008 | */ |
4007 | return 0; | 4009 | return 0; |
4008 | } else { | 4010 | } else { |
4009 | curr_aen.members.locale |= le16_to_cpu(prev_aen.members.locale); | 4011 | curr_aen.members.locale |= prev_aen.members.locale; |
4010 | 4012 | ||
4011 | if (prev_aen.members.class < curr_aen.members.class) | 4013 | if (prev_aen.members.class < curr_aen.members.class) |
4012 | curr_aen.members.class = prev_aen.members.class; | 4014 | curr_aen.members.class = prev_aen.members.class; |
@@ -4097,7 +4099,7 @@ static int megasas_start_aen(struct megasas_instance *instance) | |||
4097 | class_locale.members.class = MR_EVT_CLASS_DEBUG; | 4099 | class_locale.members.class = MR_EVT_CLASS_DEBUG; |
4098 | 4100 | ||
4099 | return megasas_register_aen(instance, | 4101 | return megasas_register_aen(instance, |
4100 | le32_to_cpu(eli.newest_seq_num) + 1, | 4102 | eli.newest_seq_num + 1, |
4101 | class_locale.word); | 4103 | class_locale.word); |
4102 | } | 4104 | } |
4103 | 4105 | ||
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index d99f41c2ca13..a04b4ff8c7f6 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c | |||
@@ -309,6 +309,117 @@ static ssize_t pm8001_ctl_aap_log_show(struct device *cdev, | |||
309 | } | 309 | } |
310 | static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); | 310 | static DEVICE_ATTR(aap_log, S_IRUGO, pm8001_ctl_aap_log_show, NULL); |
311 | /** | 311 | /** |
312 | * pm8001_ctl_ib_queue_log_show - Out bound Queue log | ||
313 | * @cdev:pointer to embedded class device | ||
314 | * @buf: the buffer returned | ||
315 | * A sysfs 'read-only' shost attribute. | ||
316 | */ | ||
317 | static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev, | ||
318 | struct device_attribute *attr, char *buf) | ||
319 | { | ||
320 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
321 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
322 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
323 | int offset; | ||
324 | char *str = buf; | ||
325 | int start = 0; | ||
326 | #define IB_MEMMAP(c) \ | ||
327 | (*(u32 *)((u8 *)pm8001_ha-> \ | ||
328 | memoryMap.region[IB].virt_ptr + \ | ||
329 | pm8001_ha->evtlog_ib_offset + (c))) | ||
330 | |||
331 | for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { | ||
332 | if (pm8001_ha->chip_id != chip_8001) | ||
333 | str += sprintf(str, "0x%08x\n", IB_MEMMAP(start)); | ||
334 | else | ||
335 | str += sprintf(str, "0x%08x\n", IB_MEMMAP(start)); | ||
336 | start = start + 4; | ||
337 | } | ||
338 | pm8001_ha->evtlog_ib_offset += SYSFS_OFFSET; | ||
339 | if ((((pm8001_ha->evtlog_ib_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) | ||
340 | && (pm8001_ha->chip_id != chip_8001)) | ||
341 | pm8001_ha->evtlog_ib_offset = 0; | ||
342 | if ((((pm8001_ha->evtlog_ib_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0) | ||
343 | && (pm8001_ha->chip_id == chip_8001)) | ||
344 | pm8001_ha->evtlog_ib_offset = 0; | ||
345 | |||
346 | return str - buf; | ||
347 | } | ||
348 | |||
349 | static DEVICE_ATTR(ib_log, S_IRUGO, pm8001_ctl_ib_queue_log_show, NULL); | ||
350 | /** | ||
351 | * pm8001_ctl_ob_queue_log_show - Out bound Queue log | ||
352 | * @cdev:pointer to embedded class device | ||
353 | * @buf: the buffer returned | ||
354 | * A sysfs 'read-only' shost attribute. | ||
355 | */ | ||
356 | |||
357 | static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev, | ||
358 | struct device_attribute *attr, char *buf) | ||
359 | { | ||
360 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
361 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
362 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
363 | int offset; | ||
364 | char *str = buf; | ||
365 | int start = 0; | ||
366 | #define OB_MEMMAP(c) \ | ||
367 | (*(u32 *)((u8 *)pm8001_ha-> \ | ||
368 | memoryMap.region[OB].virt_ptr + \ | ||
369 | pm8001_ha->evtlog_ob_offset + (c))) | ||
370 | |||
371 | for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { | ||
372 | if (pm8001_ha->chip_id != chip_8001) | ||
373 | str += sprintf(str, "0x%08x\n", OB_MEMMAP(start)); | ||
374 | else | ||
375 | str += sprintf(str, "0x%08x\n", OB_MEMMAP(start)); | ||
376 | start = start + 4; | ||
377 | } | ||
378 | pm8001_ha->evtlog_ob_offset += SYSFS_OFFSET; | ||
379 | if ((((pm8001_ha->evtlog_ob_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0) | ||
380 | && (pm8001_ha->chip_id != chip_8001)) | ||
381 | pm8001_ha->evtlog_ob_offset = 0; | ||
382 | if ((((pm8001_ha->evtlog_ob_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0) | ||
383 | && (pm8001_ha->chip_id == chip_8001)) | ||
384 | pm8001_ha->evtlog_ob_offset = 0; | ||
385 | |||
386 | return str - buf; | ||
387 | } | ||
388 | static DEVICE_ATTR(ob_log, S_IRUGO, pm8001_ctl_ob_queue_log_show, NULL); | ||
389 | /** | ||
390 | * pm8001_ctl_bios_version_show - Bios version Display | ||
391 | * @cdev:pointer to embedded class device | ||
392 | * @buf:the buffer returned | ||
393 | * A sysfs 'read-only' shost attribute. | ||
394 | */ | ||
395 | static ssize_t pm8001_ctl_bios_version_show(struct device *cdev, | ||
396 | struct device_attribute *attr, char *buf) | ||
397 | { | ||
398 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
399 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
400 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
401 | char *str = buf; | ||
402 | void *virt_addr; | ||
403 | int bios_index; | ||
404 | DECLARE_COMPLETION_ONSTACK(completion); | ||
405 | struct pm8001_ioctl_payload payload; | ||
406 | |||
407 | pm8001_ha->nvmd_completion = &completion; | ||
408 | payload.minor_function = 7; | ||
409 | payload.offset = 0; | ||
410 | payload.length = 4096; | ||
411 | payload.func_specific = kzalloc(4096, GFP_KERNEL); | ||
412 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | ||
413 | wait_for_completion(&completion); | ||
414 | virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; | ||
415 | for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT; | ||
416 | bios_index++) | ||
417 | str += sprintf(str, "%c", | ||
418 | *((u8 *)((u8 *)virt_addr+bios_index))); | ||
419 | return str - buf; | ||
420 | } | ||
421 | static DEVICE_ATTR(bios_version, S_IRUGO, pm8001_ctl_bios_version_show, NULL); | ||
422 | /** | ||
312 | * pm8001_ctl_aap_log_show - IOP event log | 423 | * pm8001_ctl_aap_log_show - IOP event log |
313 | * @cdev: pointer to embedded class device | 424 | * @cdev: pointer to embedded class device |
314 | * @buf: the buffer returned | 425 | * @buf: the buffer returned |
@@ -344,6 +455,43 @@ static ssize_t pm8001_ctl_iop_log_show(struct device *cdev, | |||
344 | } | 455 | } |
345 | static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); | 456 | static DEVICE_ATTR(iop_log, S_IRUGO, pm8001_ctl_iop_log_show, NULL); |
346 | 457 | ||
458 | /** | ||
459 | ** pm8001_ctl_fatal_log_show - fatal error logging | ||
460 | ** @cdev:pointer to embedded class device | ||
461 | ** @buf: the buffer returned | ||
462 | ** | ||
463 | ** A sysfs 'read-only' shost attribute. | ||
464 | **/ | ||
465 | |||
466 | static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev, | ||
467 | struct device_attribute *attr, char *buf) | ||
468 | { | ||
469 | u32 count; | ||
470 | |||
471 | count = pm80xx_get_fatal_dump(cdev, attr, buf); | ||
472 | return count; | ||
473 | } | ||
474 | |||
475 | static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL); | ||
476 | |||
477 | |||
478 | /** | ||
479 | ** pm8001_ctl_gsm_log_show - gsm dump collection | ||
480 | ** @cdev:pointer to embedded class device | ||
481 | ** @buf: the buffer returned | ||
482 | **A sysfs 'read-only' shost attribute. | ||
483 | **/ | ||
484 | static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev, | ||
485 | struct device_attribute *attr, char *buf) | ||
486 | { | ||
487 | u32 count; | ||
488 | |||
489 | count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf); | ||
490 | return count; | ||
491 | } | ||
492 | |||
493 | static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL); | ||
494 | |||
347 | #define FLASH_CMD_NONE 0x00 | 495 | #define FLASH_CMD_NONE 0x00 |
348 | #define FLASH_CMD_UPDATE 0x01 | 496 | #define FLASH_CMD_UPDATE 0x01 |
349 | #define FLASH_CMD_SET_NVMD 0x02 | 497 | #define FLASH_CMD_SET_NVMD 0x02 |
@@ -603,12 +751,17 @@ struct device_attribute *pm8001_host_attrs[] = { | |||
603 | &dev_attr_update_fw, | 751 | &dev_attr_update_fw, |
604 | &dev_attr_aap_log, | 752 | &dev_attr_aap_log, |
605 | &dev_attr_iop_log, | 753 | &dev_attr_iop_log, |
754 | &dev_attr_fatal_log, | ||
755 | &dev_attr_gsm_log, | ||
606 | &dev_attr_max_out_io, | 756 | &dev_attr_max_out_io, |
607 | &dev_attr_max_devices, | 757 | &dev_attr_max_devices, |
608 | &dev_attr_max_sg_list, | 758 | &dev_attr_max_sg_list, |
609 | &dev_attr_sas_spec_support, | 759 | &dev_attr_sas_spec_support, |
610 | &dev_attr_logging_level, | 760 | &dev_attr_logging_level, |
611 | &dev_attr_host_sas_address, | 761 | &dev_attr_host_sas_address, |
762 | &dev_attr_bios_version, | ||
763 | &dev_attr_ib_log, | ||
764 | &dev_attr_ob_log, | ||
612 | NULL, | 765 | NULL, |
613 | }; | 766 | }; |
614 | 767 | ||
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h index 63ad4aa0c422..d0d43a250b9e 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.h +++ b/drivers/scsi/pm8001/pm8001_ctl.h | |||
@@ -45,6 +45,8 @@ | |||
45 | #define HEADER_LEN 28 | 45 | #define HEADER_LEN 28 |
46 | #define SIZE_OFFSET 16 | 46 | #define SIZE_OFFSET 16 |
47 | 47 | ||
48 | #define BIOSOFFSET 56 | ||
49 | #define BIOS_OFFSET_LIMIT 61 | ||
48 | 50 | ||
49 | #define FLASH_OK 0x000000 | 51 | #define FLASH_OK 0x000000 |
50 | #define FAIL_OPEN_BIOS_FILE 0x000100 | 52 | #define FAIL_OPEN_BIOS_FILE 0x000100 |
@@ -53,5 +55,9 @@ | |||
53 | #define FAIL_OUT_MEMORY 0x000c00 | 55 | #define FAIL_OUT_MEMORY 0x000c00 |
54 | #define FLASH_IN_PROGRESS 0x001000 | 56 | #define FLASH_IN_PROGRESS 0x001000 |
55 | 57 | ||
58 | #define IB_OB_READ_TIMES 256 | ||
59 | #define SYSFS_OFFSET 1024 | ||
60 | #define PM80XX_IB_OB_QUEUE_SIZE (32 * 1024) | ||
61 | #define PM8001_IB_OB_QUEUE_SIZE (16 * 1024) | ||
56 | #endif /* PM8001_CTL_H_INCLUDED */ | 62 | #endif /* PM8001_CTL_H_INCLUDED */ |
57 | 63 | ||
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 479c5a7a863a..74a4bb9af07b 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
@@ -46,7 +46,10 @@ enum chip_flavors { | |||
46 | chip_8008, | 46 | chip_8008, |
47 | chip_8009, | 47 | chip_8009, |
48 | chip_8018, | 48 | chip_8018, |
49 | chip_8019 | 49 | chip_8019, |
50 | chip_8074, | ||
51 | chip_8076, | ||
52 | chip_8077 | ||
50 | }; | 53 | }; |
51 | 54 | ||
52 | enum phy_speed { | 55 | enum phy_speed { |
@@ -99,7 +102,8 @@ enum memory_region_num { | |||
99 | NVMD, /* NVM device */ | 102 | NVMD, /* NVM device */ |
100 | DEV_MEM, /* memory for devices */ | 103 | DEV_MEM, /* memory for devices */ |
101 | CCB_MEM, /* memory for command control block */ | 104 | CCB_MEM, /* memory for command control block */ |
102 | FW_FLASH /* memory for fw flash update */ | 105 | FW_FLASH, /* memory for fw flash update */ |
106 | FORENSIC_MEM /* memory for fw forensic data */ | ||
103 | }; | 107 | }; |
104 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) | 108 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) |
105 | 109 | ||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 4a2195752198..f16ece91b94a 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -1868,6 +1868,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1868 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1868 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
1869 | return; | 1869 | return; |
1870 | ts = &t->task_status; | 1870 | ts = &t->task_status; |
1871 | /* Print sas address of IO failed device */ | ||
1872 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
1873 | (status != IO_UNDERFLOW)) | ||
1874 | PM8001_FAIL_DBG(pm8001_ha, | ||
1875 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
1876 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
1877 | |||
1871 | switch (status) { | 1878 | switch (status) { |
1872 | case IO_SUCCESS: | 1879 | case IO_SUCCESS: |
1873 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" | 1880 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" |
@@ -2276,6 +2283,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2276 | u32 param; | 2283 | u32 param; |
2277 | u32 status; | 2284 | u32 status; |
2278 | u32 tag; | 2285 | u32 tag; |
2286 | int i, j; | ||
2287 | u8 sata_addr_low[4]; | ||
2288 | u32 temp_sata_addr_low; | ||
2289 | u8 sata_addr_hi[4]; | ||
2290 | u32 temp_sata_addr_hi; | ||
2279 | struct sata_completion_resp *psataPayload; | 2291 | struct sata_completion_resp *psataPayload; |
2280 | struct task_status_struct *ts; | 2292 | struct task_status_struct *ts; |
2281 | struct ata_task_resp *resp ; | 2293 | struct ata_task_resp *resp ; |
@@ -2325,7 +2337,46 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2325 | pm8001_printk("ts null\n")); | 2337 | pm8001_printk("ts null\n")); |
2326 | return; | 2338 | return; |
2327 | } | 2339 | } |
2328 | 2340 | /* Print sas address of IO failed device */ | |
2341 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
2342 | (status != IO_UNDERFLOW)) { | ||
2343 | if (!((t->dev->parent) && | ||
2344 | (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { | ||
2345 | for (i = 0 , j = 4; j <= 7 && i <= 3; i++ , j++) | ||
2346 | sata_addr_low[i] = pm8001_ha->sas_addr[j]; | ||
2347 | for (i = 0 , j = 0; j <= 3 && i <= 3; i++ , j++) | ||
2348 | sata_addr_hi[i] = pm8001_ha->sas_addr[j]; | ||
2349 | memcpy(&temp_sata_addr_low, sata_addr_low, | ||
2350 | sizeof(sata_addr_low)); | ||
2351 | memcpy(&temp_sata_addr_hi, sata_addr_hi, | ||
2352 | sizeof(sata_addr_hi)); | ||
2353 | temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff) | ||
2354 | |((temp_sata_addr_hi << 8) & | ||
2355 | 0xff0000) | | ||
2356 | ((temp_sata_addr_hi >> 8) | ||
2357 | & 0xff00) | | ||
2358 | ((temp_sata_addr_hi << 24) & | ||
2359 | 0xff000000)); | ||
2360 | temp_sata_addr_low = ((((temp_sata_addr_low >> 24) | ||
2361 | & 0xff) | | ||
2362 | ((temp_sata_addr_low << 8) | ||
2363 | & 0xff0000) | | ||
2364 | ((temp_sata_addr_low >> 8) | ||
2365 | & 0xff00) | | ||
2366 | ((temp_sata_addr_low << 24) | ||
2367 | & 0xff000000)) + | ||
2368 | pm8001_dev->attached_phy + | ||
2369 | 0x10); | ||
2370 | PM8001_FAIL_DBG(pm8001_ha, | ||
2371 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2372 | "%08x%08x", temp_sata_addr_hi, | ||
2373 | temp_sata_addr_low)); | ||
2374 | } else { | ||
2375 | PM8001_FAIL_DBG(pm8001_ha, | ||
2376 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2377 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
2378 | } | ||
2379 | } | ||
2329 | switch (status) { | 2380 | switch (status) { |
2330 | case IO_SUCCESS: | 2381 | case IO_SUCCESS: |
2331 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | 2382 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); |
@@ -3087,8 +3138,8 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, | |||
3087 | struct pm8001_device *pm8001_dev = ccb->device; | 3138 | struct pm8001_device *pm8001_dev = ccb->device; |
3088 | u32 status = le32_to_cpu(pPayload->status); | 3139 | u32 status = le32_to_cpu(pPayload->status); |
3089 | u32 device_id = le32_to_cpu(pPayload->device_id); | 3140 | u32 device_id = le32_to_cpu(pPayload->device_id); |
3090 | u8 pds = le32_to_cpu(pPayload->pds_nds) | PDS_BITS; | 3141 | u8 pds = le32_to_cpu(pPayload->pds_nds) & PDS_BITS; |
3091 | u8 nds = le32_to_cpu(pPayload->pds_nds) | NDS_BITS; | 3142 | u8 nds = le32_to_cpu(pPayload->pds_nds) & NDS_BITS; |
3092 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state " | 3143 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state " |
3093 | "from 0x%x to 0x%x status = 0x%x!\n", | 3144 | "from 0x%x to 0x%x status = 0x%x!\n", |
3094 | device_id, pds, nds, status)); | 3145 | device_id, pds, nds, status)); |
@@ -4700,6 +4751,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, | |||
4700 | sspTMCmd.tmf = cpu_to_le32(tmf->tmf); | 4751 | sspTMCmd.tmf = cpu_to_le32(tmf->tmf); |
4701 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); | 4752 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); |
4702 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); | 4753 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); |
4754 | if (pm8001_ha->chip_id != chip_8001) | ||
4755 | sspTMCmd.ds_ads_m = 0x08; | ||
4703 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4756 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
4704 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); | 4757 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); |
4705 | return ret; | 4758 | return ret; |
@@ -4778,6 +4831,16 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4778 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | 4831 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); |
4779 | break; | 4832 | break; |
4780 | } | 4833 | } |
4834 | case IOP_RDUMP: { | ||
4835 | nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP); | ||
4836 | nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); | ||
4837 | nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset); | ||
4838 | nvmd_req.resp_addr_hi = | ||
4839 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); | ||
4840 | nvmd_req.resp_addr_lo = | ||
4841 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | ||
4842 | break; | ||
4843 | } | ||
4781 | default: | 4844 | default: |
4782 | break; | 4845 | break; |
4783 | } | 4846 | } |
@@ -4938,6 +5001,89 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
4938 | return rc; | 5001 | return rc; |
4939 | } | 5002 | } |
4940 | 5003 | ||
5004 | ssize_t | ||
5005 | pm8001_get_gsm_dump(struct device *cdev, u32 length, char *buf) | ||
5006 | { | ||
5007 | u32 value, rem, offset = 0, bar = 0; | ||
5008 | u32 index, work_offset, dw_length; | ||
5009 | u32 shift_value, gsm_base, gsm_dump_offset; | ||
5010 | char *direct_data; | ||
5011 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
5012 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
5013 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
5014 | |||
5015 | direct_data = buf; | ||
5016 | gsm_dump_offset = pm8001_ha->fatal_forensic_shift_offset; | ||
5017 | |||
5018 | /* check max is 1 Mbytes */ | ||
5019 | if ((length > 0x100000) || (gsm_dump_offset & 3) || | ||
5020 | ((gsm_dump_offset + length) > 0x1000000)) | ||
5021 | return 1; | ||
5022 | |||
5023 | if (pm8001_ha->chip_id == chip_8001) | ||
5024 | bar = 2; | ||
5025 | else | ||
5026 | bar = 1; | ||
5027 | |||
5028 | work_offset = gsm_dump_offset & 0xFFFF0000; | ||
5029 | offset = gsm_dump_offset & 0x0000FFFF; | ||
5030 | gsm_dump_offset = work_offset; | ||
5031 | /* adjust length to dword boundary */ | ||
5032 | rem = length & 3; | ||
5033 | dw_length = length >> 2; | ||
5034 | |||
5035 | for (index = 0; index < dw_length; index++) { | ||
5036 | if ((work_offset + offset) & 0xFFFF0000) { | ||
5037 | if (pm8001_ha->chip_id == chip_8001) | ||
5038 | shift_value = ((gsm_dump_offset + offset) & | ||
5039 | SHIFT_REG_64K_MASK); | ||
5040 | else | ||
5041 | shift_value = (((gsm_dump_offset + offset) & | ||
5042 | SHIFT_REG_64K_MASK) >> | ||
5043 | SHIFT_REG_BIT_SHIFT); | ||
5044 | |||
5045 | if (pm8001_ha->chip_id == chip_8001) { | ||
5046 | gsm_base = GSM_BASE; | ||
5047 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
5048 | (gsm_base + shift_value))) | ||
5049 | return 1; | ||
5050 | } else { | ||
5051 | gsm_base = 0; | ||
5052 | if (-1 == pm80xx_bar4_shift(pm8001_ha, | ||
5053 | (gsm_base + shift_value))) | ||
5054 | return 1; | ||
5055 | } | ||
5056 | gsm_dump_offset = (gsm_dump_offset + offset) & | ||
5057 | 0xFFFF0000; | ||
5058 | work_offset = 0; | ||
5059 | offset = offset & 0x0000FFFF; | ||
5060 | } | ||
5061 | value = pm8001_cr32(pm8001_ha, bar, (work_offset + offset) & | ||
5062 | 0x0000FFFF); | ||
5063 | direct_data += sprintf(direct_data, "%08x ", value); | ||
5064 | offset += 4; | ||
5065 | } | ||
5066 | if (rem != 0) { | ||
5067 | value = pm8001_cr32(pm8001_ha, bar, (work_offset + offset) & | ||
5068 | 0x0000FFFF); | ||
5069 | /* xfr for non_dw */ | ||
5070 | direct_data += sprintf(direct_data, "%08x ", value); | ||
5071 | } | ||
5072 | /* Shift back to BAR4 original address */ | ||
5073 | if (pm8001_ha->chip_id == chip_8001) { | ||
5074 | if (-1 == pm8001_bar4_shift(pm8001_ha, 0)) | ||
5075 | return 1; | ||
5076 | } else { | ||
5077 | if (-1 == pm80xx_bar4_shift(pm8001_ha, 0)) | ||
5078 | return 1; | ||
5079 | } | ||
5080 | pm8001_ha->fatal_forensic_shift_offset += 1024; | ||
5081 | |||
5082 | if (pm8001_ha->fatal_forensic_shift_offset >= 0x100000) | ||
5083 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
5084 | return direct_data - buf; | ||
5085 | } | ||
5086 | |||
4941 | int | 5087 | int |
4942 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, | 5088 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, |
4943 | struct pm8001_device *pm8001_dev, u32 state) | 5089 | struct pm8001_device *pm8001_dev, u32 state) |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index d7c1e2034226..6d91e2446542 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h | |||
@@ -1027,5 +1027,8 @@ struct set_dev_state_resp { | |||
1027 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 | 1027 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 |
1028 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 | 1028 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 |
1029 | 1029 | ||
1030 | #define GSM_BASE 0x4F0000 | ||
1031 | #define SHIFT_REG_64K_MASK 0xffff0000 | ||
1032 | #define SHIFT_REG_BIT_SHIFT 8 | ||
1030 | #endif | 1033 | #endif |
1031 | 1034 | ||
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index f7c189606b84..662bf13c42f0 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -54,6 +54,9 @@ static const struct pm8001_chip_info pm8001_chips[] = { | |||
54 | [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, | 54 | [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, |
55 | [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, | 55 | [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, |
56 | [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, | 56 | [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, |
57 | [chip_8074] = {0, 8, &pm8001_80xx_dispatch,}, | ||
58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, | ||
59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, | ||
57 | }; | 60 | }; |
58 | static int pm8001_id; | 61 | static int pm8001_id; |
59 | 62 | ||
@@ -344,6 +347,10 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, | |||
344 | /* Memory region for fw flash */ | 347 | /* Memory region for fw flash */ |
345 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; | 348 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; |
346 | 349 | ||
350 | pm8001_ha->memoryMap.region[FORENSIC_MEM].num_elements = 1; | ||
351 | pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000; | ||
352 | pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000; | ||
353 | pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000; | ||
347 | for (i = 0; i < USI_MAX_MEMCNT; i++) { | 354 | for (i = 0; i < USI_MAX_MEMCNT; i++) { |
348 | if (pm8001_mem_alloc(pm8001_ha->pdev, | 355 | if (pm8001_mem_alloc(pm8001_ha->pdev, |
349 | &pm8001_ha->memoryMap.region[i].virt_ptr, | 356 | &pm8001_ha->memoryMap.region[i].virt_ptr, |
@@ -664,6 +671,31 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
664 | #endif | 671 | #endif |
665 | } | 672 | } |
666 | 673 | ||
674 | /* | ||
675 | * pm8001_get_phy_settings_info : Read phy setting values. | ||
676 | * @pm8001_ha : our hba. | ||
677 | */ | ||
678 | void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) | ||
679 | { | ||
680 | |||
681 | #ifdef PM8001_READ_VPD | ||
682 | /*OPTION ROM FLASH read for the SPC cards */ | ||
683 | DECLARE_COMPLETION_ONSTACK(completion); | ||
684 | struct pm8001_ioctl_payload payload; | ||
685 | |||
686 | pm8001_ha->nvmd_completion = &completion; | ||
687 | /* SAS ADDRESS read from flash / EEPROM */ | ||
688 | payload.minor_function = 6; | ||
689 | payload.offset = 0; | ||
690 | payload.length = 4096; | ||
691 | payload.func_specific = kzalloc(4096, GFP_KERNEL); | ||
692 | /* Read phy setting values from flash */ | ||
693 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | ||
694 | wait_for_completion(&completion); | ||
695 | pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); | ||
696 | #endif | ||
697 | } | ||
698 | |||
667 | #ifdef PM8001_USE_MSIX | 699 | #ifdef PM8001_USE_MSIX |
668 | /** | 700 | /** |
669 | * pm8001_setup_msix - enable MSI-X interrupt | 701 | * pm8001_setup_msix - enable MSI-X interrupt |
@@ -844,6 +876,10 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
844 | } | 876 | } |
845 | 877 | ||
846 | pm8001_init_sas_add(pm8001_ha); | 878 | pm8001_init_sas_add(pm8001_ha); |
879 | /* phy setting support for motherboard controller */ | ||
880 | if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && | ||
881 | pdev->subsystem_vendor != 0) | ||
882 | pm8001_get_phy_settings_info(pm8001_ha); | ||
847 | pm8001_post_sas_ha_init(shost, chip); | 883 | pm8001_post_sas_ha_init(shost, chip); |
848 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 884 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
849 | if (rc) | 885 | if (rc) |
@@ -1037,6 +1073,12 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
1037 | { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, | 1073 | { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, |
1038 | { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, | 1074 | { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, |
1039 | { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, | 1075 | { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, |
1076 | { PCI_VDEVICE(PMC_Sierra, 0x8074), chip_8074 }, | ||
1077 | { PCI_VDEVICE(ADAPTEC2, 0x8074), chip_8074 }, | ||
1078 | { PCI_VDEVICE(PMC_Sierra, 0x8076), chip_8076 }, | ||
1079 | { PCI_VDEVICE(ADAPTEC2, 0x8076), chip_8076 }, | ||
1080 | { PCI_VDEVICE(PMC_Sierra, 0x8077), chip_8077 }, | ||
1081 | { PCI_VDEVICE(ADAPTEC2, 0x8077), chip_8077 }, | ||
1040 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | 1082 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, |
1041 | PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, | 1083 | PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, |
1042 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | 1084 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, |
@@ -1057,6 +1099,24 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
1057 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, | 1099 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, |
1058 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | 1100 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, |
1059 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, | 1101 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, |
1102 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1103 | PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8074 }, | ||
1104 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1105 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8076 }, | ||
1106 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1107 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8077 }, | ||
1108 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1109 | PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8074 }, | ||
1110 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1111 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8076 }, | ||
1112 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1113 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8077 }, | ||
1114 | { PCI_VENDOR_ID_ADAPTEC2, 0x8076, | ||
1115 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8076 }, | ||
1116 | { PCI_VENDOR_ID_ADAPTEC2, 0x8077, | ||
1117 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, | ||
1118 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | ||
1119 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, | ||
1060 | {} /* terminate list */ | 1120 | {} /* terminate list */ |
1061 | }; | 1121 | }; |
1062 | 1122 | ||
@@ -1108,8 +1168,11 @@ module_init(pm8001_init); | |||
1108 | module_exit(pm8001_exit); | 1168 | module_exit(pm8001_exit); |
1109 | 1169 | ||
1110 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); | 1170 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); |
1171 | MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); | ||
1172 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); | ||
1111 | MODULE_DESCRIPTION( | 1173 | MODULE_DESCRIPTION( |
1112 | "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver"); | 1174 | "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 " |
1175 | "SAS/SATA controller driver"); | ||
1113 | MODULE_VERSION(DRV_VERSION); | 1176 | MODULE_VERSION(DRV_VERSION); |
1114 | MODULE_LICENSE("GPL"); | 1177 | MODULE_LICENSE("GPL"); |
1115 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); | 1178 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index a85d73de7c80..f4eb18e51631 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -447,7 +447,6 @@ static int pm8001_task_exec(struct sas_task *task, const int num, | |||
447 | break; | 447 | break; |
448 | case SAS_PROTOCOL_SATA: | 448 | case SAS_PROTOCOL_SATA: |
449 | case SAS_PROTOCOL_STP: | 449 | case SAS_PROTOCOL_STP: |
450 | case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: | ||
451 | rc = pm8001_task_prep_ata(pm8001_ha, ccb); | 450 | rc = pm8001_task_prep_ata(pm8001_ha, ccb); |
452 | break; | 451 | break; |
453 | default: | 452 | default: |
@@ -704,6 +703,8 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, | |||
704 | int res, retry; | 703 | int res, retry; |
705 | struct sas_task *task = NULL; | 704 | struct sas_task *task = NULL; |
706 | struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); | 705 | struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); |
706 | struct pm8001_device *pm8001_dev = dev->lldd_dev; | ||
707 | DECLARE_COMPLETION_ONSTACK(completion_setstate); | ||
707 | 708 | ||
708 | for (retry = 0; retry < 3; retry++) { | 709 | for (retry = 0; retry < 3; retry++) { |
709 | task = sas_alloc_slow_task(GFP_KERNEL); | 710 | task = sas_alloc_slow_task(GFP_KERNEL); |
@@ -729,6 +730,12 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, | |||
729 | goto ex_err; | 730 | goto ex_err; |
730 | } | 731 | } |
731 | wait_for_completion(&task->slow_task->completion); | 732 | wait_for_completion(&task->slow_task->completion); |
733 | if (pm8001_ha->chip_id != chip_8001) { | ||
734 | pm8001_dev->setds_completion = &completion_setstate; | ||
735 | PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, | ||
736 | pm8001_dev, 0x01); | ||
737 | wait_for_completion(&completion_setstate); | ||
738 | } | ||
732 | res = -TMF_RESP_FUNC_FAILED; | 739 | res = -TMF_RESP_FUNC_FAILED; |
733 | /* Even TMF timed out, return direct. */ | 740 | /* Even TMF timed out, return direct. */ |
734 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 741 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 570819464d90..6037d477a183 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -104,6 +104,9 @@ do { \ | |||
104 | 104 | ||
105 | 105 | ||
106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) | 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ | ||
108 | || (dev->device == 0X8076) \ | ||
109 | || (dev->device == 0X8077)) | ||
107 | 110 | ||
108 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ | 111 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ |
109 | extern struct list_head hba_list; | 112 | extern struct list_head hba_list; |
@@ -129,6 +132,61 @@ struct pm8001_ioctl_payload { | |||
129 | u8 *func_specific; | 132 | u8 *func_specific; |
130 | }; | 133 | }; |
131 | 134 | ||
135 | #define MPI_FATAL_ERROR_TABLE_OFFSET_MASK 0xFFFFFF | ||
136 | #define MPI_FATAL_ERROR_TABLE_SIZE(value) ((0xFF000000 & value) >> SHIFT24) | ||
137 | #define MPI_FATAL_EDUMP_TABLE_LO_OFFSET 0x00 /* HNFBUFL */ | ||
138 | #define MPI_FATAL_EDUMP_TABLE_HI_OFFSET 0x04 /* HNFBUFH */ | ||
139 | #define MPI_FATAL_EDUMP_TABLE_LENGTH 0x08 /* HNFBLEN */ | ||
140 | #define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */ | ||
141 | #define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */ | ||
142 | #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */ | ||
143 | #define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1 | ||
144 | #define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0 | ||
145 | #define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0 | ||
146 | #define MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED 0x1 | ||
147 | #define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA 0x2 | ||
148 | #define MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE 0x3 | ||
149 | #define TYPE_GSM_SPACE 1 | ||
150 | #define TYPE_QUEUE 2 | ||
151 | #define TYPE_FATAL 3 | ||
152 | #define TYPE_NON_FATAL 4 | ||
153 | #define TYPE_INBOUND 1 | ||
154 | #define TYPE_OUTBOUND 2 | ||
155 | struct forensic_data { | ||
156 | u32 data_type; | ||
157 | union { | ||
158 | struct { | ||
159 | u32 direct_len; | ||
160 | u32 direct_offset; | ||
161 | void *direct_data; | ||
162 | } gsm_buf; | ||
163 | struct { | ||
164 | u16 queue_type; | ||
165 | u16 queue_index; | ||
166 | u32 direct_len; | ||
167 | void *direct_data; | ||
168 | } queue_buf; | ||
169 | struct { | ||
170 | u32 direct_len; | ||
171 | u32 direct_offset; | ||
172 | u32 read_len; | ||
173 | void *direct_data; | ||
174 | } data_buf; | ||
175 | }; | ||
176 | }; | ||
177 | |||
178 | /* bit31-26 - mask bar */ | ||
179 | #define SCRATCH_PAD0_BAR_MASK 0xFC000000 | ||
180 | /* bit25-0 - offset mask */ | ||
181 | #define SCRATCH_PAD0_OFFSET_MASK 0x03FFFFFF | ||
182 | /* if AAP error state */ | ||
183 | #define SCRATCH_PAD0_AAPERR_MASK 0xFFFFFFFF | ||
184 | /* Inbound doorbell bit7 */ | ||
185 | #define SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP 0x80 | ||
186 | /* Inbound doorbell bit7 SPCV */ | ||
187 | #define SPCV_MSGU_CFG_TABLE_TRANSFER_DEBUG_INFO 0x80 | ||
188 | #define MAIN_MERRDCTO_MERRDCES 0xA0/* DWORD 0x28) */ | ||
189 | |||
132 | struct pm8001_dispatch { | 190 | struct pm8001_dispatch { |
133 | char *name; | 191 | char *name; |
134 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); | 192 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); |
@@ -343,6 +401,7 @@ union main_cfg_table { | |||
343 | u32 phy_attr_table_offset; | 401 | u32 phy_attr_table_offset; |
344 | u32 port_recovery_timer; | 402 | u32 port_recovery_timer; |
345 | u32 interrupt_reassertion_delay; | 403 | u32 interrupt_reassertion_delay; |
404 | u32 fatal_n_non_fatal_dump; /* 0x28 */ | ||
346 | } pm80xx_tbl; | 405 | } pm80xx_tbl; |
347 | }; | 406 | }; |
348 | 407 | ||
@@ -417,6 +476,13 @@ struct pm8001_hba_info { | |||
417 | struct pm8001_hba_memspace io_mem[6]; | 476 | struct pm8001_hba_memspace io_mem[6]; |
418 | struct mpi_mem_req memoryMap; | 477 | struct mpi_mem_req memoryMap; |
419 | struct encrypt encrypt_info; /* support encryption */ | 478 | struct encrypt encrypt_info; /* support encryption */ |
479 | struct forensic_data forensic_info; | ||
480 | u32 fatal_bar_loc; | ||
481 | u32 forensic_last_offset; | ||
482 | u32 fatal_forensic_shift_offset; | ||
483 | u32 forensic_fatal_step; | ||
484 | u32 evtlog_ib_offset; | ||
485 | u32 evtlog_ob_offset; | ||
420 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ | 486 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ |
421 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ | 487 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ |
422 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ | 488 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ |
@@ -425,6 +491,7 @@ struct pm8001_hba_info { | |||
425 | void __iomem *pspa_q_tbl_addr; | 491 | void __iomem *pspa_q_tbl_addr; |
426 | /*MPI SAS PHY attributes Queue Config Table Addr*/ | 492 | /*MPI SAS PHY attributes Queue Config Table Addr*/ |
427 | void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ | 493 | void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ |
494 | void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */ | ||
428 | union main_cfg_table main_cfg_tbl; | 495 | union main_cfg_table main_cfg_tbl; |
429 | union general_status_table gs_tbl; | 496 | union general_status_table gs_tbl; |
430 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; | 497 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; |
@@ -629,7 +696,12 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | |||
629 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | 696 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); |
630 | 697 | ||
631 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 698 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
632 | 699 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | |
700 | u32 length, u8 *buf); | ||
701 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | ||
702 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | ||
703 | struct device_attribute *attr, char *buf); | ||
704 | ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf); | ||
633 | /* ctl shared API */ | 705 | /* ctl shared API */ |
634 | extern struct device_attribute *pm8001_host_attrs[]; | 706 | extern struct device_attribute *pm8001_host_attrs[]; |
635 | 707 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9f91030211e8..8987b1706216 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -45,6 +45,228 @@ | |||
45 | 45 | ||
46 | #define SMP_DIRECT 1 | 46 | #define SMP_DIRECT 1 |
47 | #define SMP_INDIRECT 2 | 47 | #define SMP_INDIRECT 2 |
48 | |||
49 | |||
50 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) | ||
51 | { | ||
52 | u32 reg_val; | ||
53 | unsigned long start; | ||
54 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value); | ||
55 | /* confirm the setting is written */ | ||
56 | start = jiffies + HZ; /* 1 sec */ | ||
57 | do { | ||
58 | reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER); | ||
59 | } while ((reg_val != shift_value) && time_before(jiffies, start)); | ||
60 | if (reg_val != shift_value) { | ||
61 | PM8001_FAIL_DBG(pm8001_ha, | ||
62 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
63 | " = 0x%x\n", reg_val)); | ||
64 | return -1; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, | ||
70 | const void *destination, | ||
71 | u32 dw_count, u32 bus_base_number) | ||
72 | { | ||
73 | u32 index, value, offset; | ||
74 | u32 *destination1; | ||
75 | destination1 = (u32 *)destination; | ||
76 | |||
77 | for (index = 0; index < dw_count; index += 4, destination1++) { | ||
78 | offset = (soffset + index / 4); | ||
79 | if (offset < (64 * 1024)) { | ||
80 | value = pm8001_cr32(pm8001_ha, bus_base_number, offset); | ||
81 | *destination1 = cpu_to_le32(value); | ||
82 | } | ||
83 | } | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | ||
88 | struct device_attribute *attr, char *buf) | ||
89 | { | ||
90 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
91 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
92 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
93 | void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr; | ||
94 | u32 status = 1; | ||
95 | u32 accum_len , reg_val, index, *temp; | ||
96 | unsigned long start; | ||
97 | u8 *direct_data; | ||
98 | char *fatal_error_data = buf; | ||
99 | |||
100 | pm8001_ha->forensic_info.data_buf.direct_data = buf; | ||
101 | if (pm8001_ha->chip_id == chip_8001) { | ||
102 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
103 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
104 | "Not supported for SPC controller"); | ||
105 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
106 | (char *)buf; | ||
107 | } | ||
108 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
109 | PM8001_IO_DBG(pm8001_ha, | ||
110 | pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); | ||
111 | direct_data = (u8 *)fatal_error_data; | ||
112 | pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; | ||
113 | pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; | ||
114 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
115 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
116 | |||
117 | pm8001_ha->forensic_info.data_buf.direct_data = direct_data; | ||
118 | } | ||
119 | |||
120 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
121 | /* start to get data */ | ||
122 | /* Program the MEMBASE II Shifting Register with 0x00.*/ | ||
123 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
124 | pm8001_ha->fatal_forensic_shift_offset); | ||
125 | pm8001_ha->forensic_last_offset = 0; | ||
126 | pm8001_ha->forensic_fatal_step = 0; | ||
127 | pm8001_ha->fatal_bar_loc = 0; | ||
128 | } | ||
129 | /* Read until accum_len is retrived */ | ||
130 | accum_len = pm8001_mr32(fatal_table_address, | ||
131 | MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); | ||
132 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n", | ||
133 | accum_len)); | ||
134 | if (accum_len == 0xFFFFFFFF) { | ||
135 | PM8001_IO_DBG(pm8001_ha, | ||
136 | pm8001_printk("Possible PCI issue 0x%x not expected\n", | ||
137 | accum_len)); | ||
138 | return status; | ||
139 | } | ||
140 | if (accum_len == 0 || accum_len >= 0x100000) { | ||
141 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
142 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
143 | "%08x ", 0xFFFFFFFF); | ||
144 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
145 | (char *)buf; | ||
146 | } | ||
147 | temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; | ||
148 | if (pm8001_ha->forensic_fatal_step == 0) { | ||
149 | moreData: | ||
150 | if (pm8001_ha->forensic_info.data_buf.direct_data) { | ||
151 | /* Data is in bar, copy to host memory */ | ||
152 | pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc, | ||
153 | pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, | ||
154 | pm8001_ha->forensic_info.data_buf.direct_len , | ||
155 | 1); | ||
156 | } | ||
157 | pm8001_ha->fatal_bar_loc += | ||
158 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
159 | pm8001_ha->forensic_info.data_buf.direct_offset += | ||
160 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
161 | pm8001_ha->forensic_last_offset += | ||
162 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
163 | pm8001_ha->forensic_info.data_buf.read_len = | ||
164 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
165 | |||
166 | if (pm8001_ha->forensic_last_offset >= accum_len) { | ||
167 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
168 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
169 | "%08x ", 3); | ||
170 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
171 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
172 | sprintf(pm8001_ha-> | ||
173 | forensic_info.data_buf.direct_data, | ||
174 | "%08x ", *(temp + index)); | ||
175 | } | ||
176 | |||
177 | pm8001_ha->fatal_bar_loc = 0; | ||
178 | pm8001_ha->forensic_fatal_step = 1; | ||
179 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
180 | pm8001_ha->forensic_last_offset = 0; | ||
181 | status = 0; | ||
182 | return (char *)pm8001_ha-> | ||
183 | forensic_info.data_buf.direct_data - | ||
184 | (char *)buf; | ||
185 | } | ||
186 | if (pm8001_ha->fatal_bar_loc < (64 * 1024)) { | ||
187 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
188 | sprintf(pm8001_ha-> | ||
189 | forensic_info.data_buf.direct_data, | ||
190 | "%08x ", 2); | ||
191 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
192 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
193 | sprintf(pm8001_ha-> | ||
194 | forensic_info.data_buf.direct_data, | ||
195 | "%08x ", *(temp + index)); | ||
196 | } | ||
197 | status = 0; | ||
198 | return (char *)pm8001_ha-> | ||
199 | forensic_info.data_buf.direct_data - | ||
200 | (char *)buf; | ||
201 | } | ||
202 | |||
203 | /* Increment the MEMBASE II Shifting Register value by 0x100.*/ | ||
204 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
205 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
206 | "%08x ", 2); | ||
207 | for (index = 0; index < 256; index++) { | ||
208 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
209 | sprintf(pm8001_ha-> | ||
210 | forensic_info.data_buf.direct_data, | ||
211 | "%08x ", *(temp + index)); | ||
212 | } | ||
213 | pm8001_ha->fatal_forensic_shift_offset += 0x100; | ||
214 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
215 | pm8001_ha->fatal_forensic_shift_offset); | ||
216 | pm8001_ha->fatal_bar_loc = 0; | ||
217 | status = 0; | ||
218 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
219 | (char *)buf; | ||
220 | } | ||
221 | if (pm8001_ha->forensic_fatal_step == 1) { | ||
222 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
223 | /* Read 64K of the debug data. */ | ||
224 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
225 | pm8001_ha->fatal_forensic_shift_offset); | ||
226 | pm8001_mw32(fatal_table_address, | ||
227 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, | ||
228 | MPI_FATAL_EDUMP_HANDSHAKE_RDY); | ||
229 | |||
230 | /* Poll FDDHSHK until clear */ | ||
231 | start = jiffies + (2 * HZ); /* 2 sec */ | ||
232 | |||
233 | do { | ||
234 | reg_val = pm8001_mr32(fatal_table_address, | ||
235 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE); | ||
236 | } while ((reg_val) && time_before(jiffies, start)); | ||
237 | |||
238 | if (reg_val != 0) { | ||
239 | PM8001_FAIL_DBG(pm8001_ha, | ||
240 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
241 | " = 0x%x\n", reg_val)); | ||
242 | return -1; | ||
243 | } | ||
244 | |||
245 | /* Read the next 64K of the debug data. */ | ||
246 | pm8001_ha->forensic_fatal_step = 0; | ||
247 | if (pm8001_mr32(fatal_table_address, | ||
248 | MPI_FATAL_EDUMP_TABLE_STATUS) != | ||
249 | MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { | ||
250 | pm8001_mw32(fatal_table_address, | ||
251 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0); | ||
252 | goto moreData; | ||
253 | } else { | ||
254 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
255 | sprintf(pm8001_ha-> | ||
256 | forensic_info.data_buf.direct_data, | ||
257 | "%08x ", 4); | ||
258 | pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF; | ||
259 | pm8001_ha->forensic_info.data_buf.direct_len = 0; | ||
260 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
261 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
262 | status = 0; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
267 | (char *)buf; | ||
268 | } | ||
269 | |||
48 | /** | 270 | /** |
49 | * read_main_config_table - read the configure table and save it. | 271 | * read_main_config_table - read the configure table and save it. |
50 | * @pm8001_ha: our hba card information | 272 | * @pm8001_ha: our hba card information |
@@ -430,7 +652,11 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) | |||
430 | table is updated */ | 652 | table is updated */ |
431 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); | 653 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); |
432 | /* wait until Inbound DoorBell Clear Register toggled */ | 654 | /* wait until Inbound DoorBell Clear Register toggled */ |
433 | max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */ | 655 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
656 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
657 | } else { | ||
658 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
659 | } | ||
434 | do { | 660 | do { |
435 | udelay(1); | 661 | udelay(1); |
436 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 662 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -579,6 +805,9 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | |||
579 | pm8001_ha->pspa_q_tbl_addr = | 805 | pm8001_ha->pspa_q_tbl_addr = |
580 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & | 806 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & |
581 | 0xFFFFFF); | 807 | 0xFFFFFF); |
808 | pm8001_ha->fatal_tbl_addr = | ||
809 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) & | ||
810 | 0xFFFFFF); | ||
582 | 811 | ||
583 | PM8001_INIT_DBG(pm8001_ha, | 812 | PM8001_INIT_DBG(pm8001_ha, |
584 | pm8001_printk("GST OFFSET 0x%x\n", | 813 | pm8001_printk("GST OFFSET 0x%x\n", |
@@ -913,7 +1142,11 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) | |||
913 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); | 1142 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); |
914 | 1143 | ||
915 | /* wait until Inbound DoorBell Clear Register toggled */ | 1144 | /* wait until Inbound DoorBell Clear Register toggled */ |
916 | max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */ | 1145 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
1146 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
1147 | } else { | ||
1148 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
1149 | } | ||
917 | do { | 1150 | do { |
918 | udelay(1); | 1151 | udelay(1); |
919 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 1152 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -959,6 +1192,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
959 | { | 1192 | { |
960 | u32 regval; | 1193 | u32 regval; |
961 | u32 bootloader_state; | 1194 | u32 bootloader_state; |
1195 | u32 ibutton0, ibutton1; | ||
962 | 1196 | ||
963 | /* Check if MPI is in ready state to reset */ | 1197 | /* Check if MPI is in ready state to reset */ |
964 | if (mpi_uninit_check(pm8001_ha) != 0) { | 1198 | if (mpi_uninit_check(pm8001_ha) != 0) { |
@@ -1017,7 +1251,27 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
1017 | if (-1 == check_fw_ready(pm8001_ha)) { | 1251 | if (-1 == check_fw_ready(pm8001_ha)) { |
1018 | PM8001_FAIL_DBG(pm8001_ha, | 1252 | PM8001_FAIL_DBG(pm8001_ha, |
1019 | pm8001_printk("Firmware is not ready!\n")); | 1253 | pm8001_printk("Firmware is not ready!\n")); |
1020 | return -EBUSY; | 1254 | /* check iButton feature support for motherboard controller */ |
1255 | if (pm8001_ha->pdev->subsystem_vendor != | ||
1256 | PCI_VENDOR_ID_ADAPTEC2 && | ||
1257 | pm8001_ha->pdev->subsystem_vendor != 0) { | ||
1258 | ibutton0 = pm8001_cr32(pm8001_ha, 0, | ||
1259 | MSGU_HOST_SCRATCH_PAD_6); | ||
1260 | ibutton1 = pm8001_cr32(pm8001_ha, 0, | ||
1261 | MSGU_HOST_SCRATCH_PAD_7); | ||
1262 | if (!ibutton0 && !ibutton1) { | ||
1263 | PM8001_FAIL_DBG(pm8001_ha, | ||
1264 | pm8001_printk("iButton Feature is" | ||
1265 | " not Available!!!\n")); | ||
1266 | return -EBUSY; | ||
1267 | } | ||
1268 | if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) { | ||
1269 | PM8001_FAIL_DBG(pm8001_ha, | ||
1270 | pm8001_printk("CRC Check for iButton" | ||
1271 | " Feature Failed!!!\n")); | ||
1272 | return -EBUSY; | ||
1273 | } | ||
1274 | } | ||
1021 | } | 1275 | } |
1022 | PM8001_INIT_DBG(pm8001_ha, | 1276 | PM8001_INIT_DBG(pm8001_ha, |
1023 | pm8001_printk("SPCv soft reset Complete\n")); | 1277 | pm8001_printk("SPCv soft reset Complete\n")); |
@@ -1268,6 +1522,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1268 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1522 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
1269 | return; | 1523 | return; |
1270 | ts = &t->task_status; | 1524 | ts = &t->task_status; |
1525 | /* Print sas address of IO failed device */ | ||
1526 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
1527 | (status != IO_UNDERFLOW)) | ||
1528 | PM8001_FAIL_DBG(pm8001_ha, | ||
1529 | pm8001_printk("SAS Address of IO Failure Drive" | ||
1530 | ":%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
1531 | |||
1271 | switch (status) { | 1532 | switch (status) { |
1272 | case IO_SUCCESS: | 1533 | case IO_SUCCESS: |
1273 | PM8001_IO_DBG(pm8001_ha, | 1534 | PM8001_IO_DBG(pm8001_ha, |
@@ -1691,6 +1952,10 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1691 | u32 param; | 1952 | u32 param; |
1692 | u32 status; | 1953 | u32 status; |
1693 | u32 tag; | 1954 | u32 tag; |
1955 | int i, j; | ||
1956 | u8 sata_addr_low[4]; | ||
1957 | u32 temp_sata_addr_low, temp_sata_addr_hi; | ||
1958 | u8 sata_addr_hi[4]; | ||
1694 | struct sata_completion_resp *psataPayload; | 1959 | struct sata_completion_resp *psataPayload; |
1695 | struct task_status_struct *ts; | 1960 | struct task_status_struct *ts; |
1696 | struct ata_task_resp *resp ; | 1961 | struct ata_task_resp *resp ; |
@@ -1740,7 +2005,47 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1740 | pm8001_printk("ts null\n")); | 2005 | pm8001_printk("ts null\n")); |
1741 | return; | 2006 | return; |
1742 | } | 2007 | } |
2008 | /* Print sas address of IO failed device */ | ||
2009 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
2010 | (status != IO_UNDERFLOW)) { | ||
2011 | if (!((t->dev->parent) && | ||
2012 | (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { | ||
2013 | for (i = 0 , j = 4; i <= 3 && j <= 7; i++ , j++) | ||
2014 | sata_addr_low[i] = pm8001_ha->sas_addr[j]; | ||
2015 | for (i = 0 , j = 0; i <= 3 && j <= 3; i++ , j++) | ||
2016 | sata_addr_hi[i] = pm8001_ha->sas_addr[j]; | ||
2017 | memcpy(&temp_sata_addr_low, sata_addr_low, | ||
2018 | sizeof(sata_addr_low)); | ||
2019 | memcpy(&temp_sata_addr_hi, sata_addr_hi, | ||
2020 | sizeof(sata_addr_hi)); | ||
2021 | temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff) | ||
2022 | |((temp_sata_addr_hi << 8) & | ||
2023 | 0xff0000) | | ||
2024 | ((temp_sata_addr_hi >> 8) | ||
2025 | & 0xff00) | | ||
2026 | ((temp_sata_addr_hi << 24) & | ||
2027 | 0xff000000)); | ||
2028 | temp_sata_addr_low = ((((temp_sata_addr_low >> 24) | ||
2029 | & 0xff) | | ||
2030 | ((temp_sata_addr_low << 8) | ||
2031 | & 0xff0000) | | ||
2032 | ((temp_sata_addr_low >> 8) | ||
2033 | & 0xff00) | | ||
2034 | ((temp_sata_addr_low << 24) | ||
2035 | & 0xff000000)) + | ||
2036 | pm8001_dev->attached_phy + | ||
2037 | 0x10); | ||
2038 | PM8001_FAIL_DBG(pm8001_ha, | ||
2039 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2040 | "%08x%08x", temp_sata_addr_hi, | ||
2041 | temp_sata_addr_low)); | ||
1743 | 2042 | ||
2043 | } else { | ||
2044 | PM8001_FAIL_DBG(pm8001_ha, | ||
2045 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2046 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
2047 | } | ||
2048 | } | ||
1744 | switch (status) { | 2049 | switch (status) { |
1745 | case IO_SUCCESS: | 2050 | case IO_SUCCESS: |
1746 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | 2051 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); |
@@ -3103,9 +3408,27 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3103 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | 3408 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, |
3104 | void *piomb) | 3409 | void *piomb) |
3105 | { | 3410 | { |
3106 | PM8001_MSG_DBG(pm8001_ha, | 3411 | u8 page_code; |
3107 | pm8001_printk(" pm80xx_addition_functionality\n")); | 3412 | struct set_phy_profile_resp *pPayload = |
3413 | (struct set_phy_profile_resp *)(piomb + 4); | ||
3414 | u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid); | ||
3415 | u32 status = le32_to_cpu(pPayload->status); | ||
3108 | 3416 | ||
3417 | page_code = (u8)((ppc_phyid & 0xFF00) >> 8); | ||
3418 | if (status) { | ||
3419 | /* status is FAILED */ | ||
3420 | PM8001_FAIL_DBG(pm8001_ha, | ||
3421 | pm8001_printk("PhyProfile command failed with status " | ||
3422 | "0x%08X \n", status)); | ||
3423 | return -1; | ||
3424 | } else { | ||
3425 | if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { | ||
3426 | PM8001_FAIL_DBG(pm8001_ha, | ||
3427 | pm8001_printk("Invalid page code 0x%X\n", | ||
3428 | page_code)); | ||
3429 | return -1; | ||
3430 | } | ||
3431 | } | ||
3109 | return 0; | 3432 | return 0; |
3110 | } | 3433 | } |
3111 | 3434 | ||
@@ -3484,8 +3807,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3484 | else | 3807 | else |
3485 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; | 3808 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; |
3486 | 3809 | ||
3487 | /* DIRECT MODE support only in spcv/ve */ | ||
3488 | pm8001_ha->smp_exp_mode = SMP_DIRECT; | ||
3489 | 3810 | ||
3490 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); | 3811 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); |
3491 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); | 3812 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); |
@@ -3501,7 +3822,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3501 | /* exclude top 4 bytes for SMP req header */ | 3822 | /* exclude top 4 bytes for SMP req header */ |
3502 | smp_cmd.long_smp_req.long_req_addr = | 3823 | smp_cmd.long_smp_req.long_req_addr = |
3503 | cpu_to_le64((u64)sg_dma_address | 3824 | cpu_to_le64((u64)sg_dma_address |
3504 | (&task->smp_task.smp_req) - 4); | 3825 | (&task->smp_task.smp_req) + 4); |
3505 | /* exclude 4 bytes for SMP req header and CRC */ | 3826 | /* exclude 4 bytes for SMP req header and CRC */ |
3506 | smp_cmd.long_smp_req.long_req_size = | 3827 | smp_cmd.long_smp_req.long_req_size = |
3507 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); | 3828 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); |
@@ -3604,10 +3925,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3604 | struct ssp_ini_io_start_req ssp_cmd; | 3925 | struct ssp_ini_io_start_req ssp_cmd; |
3605 | u32 tag = ccb->ccb_tag; | 3926 | u32 tag = ccb->ccb_tag; |
3606 | int ret; | 3927 | int ret; |
3607 | u64 phys_addr; | 3928 | u64 phys_addr, start_addr, end_addr; |
3929 | u32 end_addr_high, end_addr_low; | ||
3608 | struct inbound_queue_table *circularQ; | 3930 | struct inbound_queue_table *circularQ; |
3609 | static u32 inb; | 3931 | u32 q_index; |
3610 | static u32 outb; | ||
3611 | u32 opc = OPC_INB_SSPINIIOSTART; | 3932 | u32 opc = OPC_INB_SSPINIIOSTART; |
3612 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); | 3933 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); |
3613 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); | 3934 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); |
@@ -3626,7 +3947,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3626 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); | 3947 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); |
3627 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, | 3948 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, |
3628 | task->ssp_task.cmd->cmd_len); | 3949 | task->ssp_task.cmd->cmd_len); |
3629 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 3950 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
3951 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3630 | 3952 | ||
3631 | /* Check if encryption is set */ | 3953 | /* Check if encryption is set */ |
3632 | if (pm8001_ha->chip->encrypt && | 3954 | if (pm8001_ha->chip->encrypt && |
@@ -3658,6 +3980,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3658 | cpu_to_le32(upper_32_bits(dma_addr)); | 3980 | cpu_to_le32(upper_32_bits(dma_addr)); |
3659 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 3981 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3660 | ssp_cmd.enc_esgl = 0; | 3982 | ssp_cmd.enc_esgl = 0; |
3983 | /* Check 4G Boundary */ | ||
3984 | start_addr = cpu_to_le64(dma_addr); | ||
3985 | end_addr = (start_addr + ssp_cmd.enc_len) - 1; | ||
3986 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
3987 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
3988 | if (end_addr_high != ssp_cmd.enc_addr_high) { | ||
3989 | PM8001_FAIL_DBG(pm8001_ha, | ||
3990 | pm8001_printk("The sg list address " | ||
3991 | "start_addr=0x%016llx data_len=0x%x " | ||
3992 | "end_addr_high=0x%08x end_addr_low=" | ||
3993 | "0x%08x has crossed 4G boundary\n", | ||
3994 | start_addr, ssp_cmd.enc_len, | ||
3995 | end_addr_high, end_addr_low)); | ||
3996 | pm8001_chip_make_sg(task->scatter, 1, | ||
3997 | ccb->buf_prd); | ||
3998 | phys_addr = ccb->ccb_dma_handle + | ||
3999 | offsetof(struct pm8001_ccb_info, | ||
4000 | buf_prd[0]); | ||
4001 | ssp_cmd.enc_addr_low = | ||
4002 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4003 | ssp_cmd.enc_addr_high = | ||
4004 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4005 | ssp_cmd.enc_esgl = cpu_to_le32(1<<31); | ||
4006 | } | ||
3661 | } else if (task->num_scatter == 0) { | 4007 | } else if (task->num_scatter == 0) { |
3662 | ssp_cmd.enc_addr_low = 0; | 4008 | ssp_cmd.enc_addr_low = 0; |
3663 | ssp_cmd.enc_addr_high = 0; | 4009 | ssp_cmd.enc_addr_high = 0; |
@@ -3674,7 +4020,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3674 | } else { | 4020 | } else { |
3675 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4021 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3676 | "Sending Normal SAS command 0x%x inb q %x\n", | 4022 | "Sending Normal SAS command 0x%x inb q %x\n", |
3677 | task->ssp_task.cmd->cmnd[0], inb)); | 4023 | task->ssp_task.cmd->cmnd[0], q_index)); |
3678 | /* fill in PRD (scatter/gather) table, if any */ | 4024 | /* fill in PRD (scatter/gather) table, if any */ |
3679 | if (task->num_scatter > 1) { | 4025 | if (task->num_scatter > 1) { |
3680 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, | 4026 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, |
@@ -3693,6 +4039,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3693 | cpu_to_le32(upper_32_bits(dma_addr)); | 4039 | cpu_to_le32(upper_32_bits(dma_addr)); |
3694 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | 4040 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); |
3695 | ssp_cmd.esgl = 0; | 4041 | ssp_cmd.esgl = 0; |
4042 | /* Check 4G Boundary */ | ||
4043 | start_addr = cpu_to_le64(dma_addr); | ||
4044 | end_addr = (start_addr + ssp_cmd.len) - 1; | ||
4045 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4046 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4047 | if (end_addr_high != ssp_cmd.addr_high) { | ||
4048 | PM8001_FAIL_DBG(pm8001_ha, | ||
4049 | pm8001_printk("The sg list address " | ||
4050 | "start_addr=0x%016llx data_len=0x%x " | ||
4051 | "end_addr_high=0x%08x end_addr_low=" | ||
4052 | "0x%08x has crossed 4G boundary\n", | ||
4053 | start_addr, ssp_cmd.len, | ||
4054 | end_addr_high, end_addr_low)); | ||
4055 | pm8001_chip_make_sg(task->scatter, 1, | ||
4056 | ccb->buf_prd); | ||
4057 | phys_addr = ccb->ccb_dma_handle + | ||
4058 | offsetof(struct pm8001_ccb_info, | ||
4059 | buf_prd[0]); | ||
4060 | ssp_cmd.addr_low = | ||
4061 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4062 | ssp_cmd.addr_high = | ||
4063 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4064 | ssp_cmd.esgl = cpu_to_le32(1<<31); | ||
4065 | } | ||
3696 | } else if (task->num_scatter == 0) { | 4066 | } else if (task->num_scatter == 0) { |
3697 | ssp_cmd.addr_low = 0; | 4067 | ssp_cmd.addr_low = 0; |
3698 | ssp_cmd.addr_high = 0; | 4068 | ssp_cmd.addr_high = 0; |
@@ -3700,11 +4070,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3700 | ssp_cmd.esgl = 0; | 4070 | ssp_cmd.esgl = 0; |
3701 | } | 4071 | } |
3702 | } | 4072 | } |
3703 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++); | 4073 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; |
3704 | 4074 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | |
3705 | /* rotate the outb queue */ | 4075 | &ssp_cmd, q_index); |
3706 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3707 | |||
3708 | return ret; | 4076 | return ret; |
3709 | } | 4077 | } |
3710 | 4078 | ||
@@ -3716,18 +4084,19 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3716 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; | 4084 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; |
3717 | u32 tag = ccb->ccb_tag; | 4085 | u32 tag = ccb->ccb_tag; |
3718 | int ret; | 4086 | int ret; |
3719 | static u32 inb; | 4087 | u32 q_index; |
3720 | static u32 outb; | ||
3721 | struct sata_start_req sata_cmd; | 4088 | struct sata_start_req sata_cmd; |
3722 | u32 hdr_tag, ncg_tag = 0; | 4089 | u32 hdr_tag, ncg_tag = 0; |
3723 | u64 phys_addr; | 4090 | u64 phys_addr, start_addr, end_addr; |
4091 | u32 end_addr_high, end_addr_low; | ||
3724 | u32 ATAP = 0x0; | 4092 | u32 ATAP = 0x0; |
3725 | u32 dir; | 4093 | u32 dir; |
3726 | struct inbound_queue_table *circularQ; | 4094 | struct inbound_queue_table *circularQ; |
3727 | unsigned long flags; | 4095 | unsigned long flags; |
3728 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 4096 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
3729 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 4097 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
3730 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4098 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
4099 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3731 | 4100 | ||
3732 | if (task->data_dir == PCI_DMA_NONE) { | 4101 | if (task->data_dir == PCI_DMA_NONE) { |
3733 | ATAP = 0x04; /* no data*/ | 4102 | ATAP = 0x04; /* no data*/ |
@@ -3788,6 +4157,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3788 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); | 4157 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); |
3789 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 4158 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3790 | sata_cmd.enc_esgl = 0; | 4159 | sata_cmd.enc_esgl = 0; |
4160 | /* Check 4G Boundary */ | ||
4161 | start_addr = cpu_to_le64(dma_addr); | ||
4162 | end_addr = (start_addr + sata_cmd.enc_len) - 1; | ||
4163 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4164 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4165 | if (end_addr_high != sata_cmd.enc_addr_high) { | ||
4166 | PM8001_FAIL_DBG(pm8001_ha, | ||
4167 | pm8001_printk("The sg list address " | ||
4168 | "start_addr=0x%016llx data_len=0x%x " | ||
4169 | "end_addr_high=0x%08x end_addr_low" | ||
4170 | "=0x%08x has crossed 4G boundary\n", | ||
4171 | start_addr, sata_cmd.enc_len, | ||
4172 | end_addr_high, end_addr_low)); | ||
4173 | pm8001_chip_make_sg(task->scatter, 1, | ||
4174 | ccb->buf_prd); | ||
4175 | phys_addr = ccb->ccb_dma_handle + | ||
4176 | offsetof(struct pm8001_ccb_info, | ||
4177 | buf_prd[0]); | ||
4178 | sata_cmd.enc_addr_low = | ||
4179 | lower_32_bits(phys_addr); | ||
4180 | sata_cmd.enc_addr_high = | ||
4181 | upper_32_bits(phys_addr); | ||
4182 | sata_cmd.enc_esgl = | ||
4183 | cpu_to_le32(1 << 31); | ||
4184 | } | ||
3791 | } else if (task->num_scatter == 0) { | 4185 | } else if (task->num_scatter == 0) { |
3792 | sata_cmd.enc_addr_low = 0; | 4186 | sata_cmd.enc_addr_low = 0; |
3793 | sata_cmd.enc_addr_high = 0; | 4187 | sata_cmd.enc_addr_high = 0; |
@@ -3808,7 +4202,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3808 | } else { | 4202 | } else { |
3809 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4203 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3810 | "Sending Normal SATA command 0x%x inb %x\n", | 4204 | "Sending Normal SATA command 0x%x inb %x\n", |
3811 | sata_cmd.sata_fis.command, inb)); | 4205 | sata_cmd.sata_fis.command, q_index)); |
3812 | /* dad (bit 0-1) is 0 */ | 4206 | /* dad (bit 0-1) is 0 */ |
3813 | sata_cmd.ncqtag_atap_dir_m_dad = | 4207 | sata_cmd.ncqtag_atap_dir_m_dad = |
3814 | cpu_to_le32(((ncg_tag & 0xff)<<16) | | 4208 | cpu_to_le32(((ncg_tag & 0xff)<<16) | |
@@ -3829,6 +4223,30 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3829 | sata_cmd.addr_high = upper_32_bits(dma_addr); | 4223 | sata_cmd.addr_high = upper_32_bits(dma_addr); |
3830 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | 4224 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); |
3831 | sata_cmd.esgl = 0; | 4225 | sata_cmd.esgl = 0; |
4226 | /* Check 4G Boundary */ | ||
4227 | start_addr = cpu_to_le64(dma_addr); | ||
4228 | end_addr = (start_addr + sata_cmd.len) - 1; | ||
4229 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4230 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4231 | if (end_addr_high != sata_cmd.addr_high) { | ||
4232 | PM8001_FAIL_DBG(pm8001_ha, | ||
4233 | pm8001_printk("The sg list address " | ||
4234 | "start_addr=0x%016llx data_len=0x%x" | ||
4235 | "end_addr_high=0x%08x end_addr_low=" | ||
4236 | "0x%08x has crossed 4G boundary\n", | ||
4237 | start_addr, sata_cmd.len, | ||
4238 | end_addr_high, end_addr_low)); | ||
4239 | pm8001_chip_make_sg(task->scatter, 1, | ||
4240 | ccb->buf_prd); | ||
4241 | phys_addr = ccb->ccb_dma_handle + | ||
4242 | offsetof(struct pm8001_ccb_info, | ||
4243 | buf_prd[0]); | ||
4244 | sata_cmd.addr_low = | ||
4245 | lower_32_bits(phys_addr); | ||
4246 | sata_cmd.addr_high = | ||
4247 | upper_32_bits(phys_addr); | ||
4248 | sata_cmd.esgl = cpu_to_le32(1 << 31); | ||
4249 | } | ||
3832 | } else if (task->num_scatter == 0) { | 4250 | } else if (task->num_scatter == 0) { |
3833 | sata_cmd.addr_low = 0; | 4251 | sata_cmd.addr_low = 0; |
3834 | sata_cmd.addr_high = 0; | 4252 | sata_cmd.addr_high = 0; |
@@ -3905,12 +4323,9 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3905 | } | 4323 | } |
3906 | } | 4324 | } |
3907 | } | 4325 | } |
3908 | 4326 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; | |
3909 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | 4327 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, |
3910 | &sata_cmd, outb++); | 4328 | &sata_cmd, q_index); |
3911 | |||
3912 | /* rotate the outb queue */ | ||
3913 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3914 | return ret; | 4329 | return ret; |
3915 | } | 4330 | } |
3916 | 4331 | ||
@@ -3941,9 +4356,16 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | |||
3941 | ** [14] 0b disable spin up hold; 1b enable spin up hold | 4356 | ** [14] 0b disable spin up hold; 1b enable spin up hold |
3942 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST | 4357 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST |
3943 | */ | 4358 | */ |
3944 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | 4359 | if (!IS_SPCV_12G(pm8001_ha->pdev)) |
3945 | LINKMODE_AUTO | LINKRATE_15 | | 4360 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | |
3946 | LINKRATE_30 | LINKRATE_60 | phy_id); | 4361 | LINKMODE_AUTO | LINKRATE_15 | |
4362 | LINKRATE_30 | LINKRATE_60 | phy_id); | ||
4363 | else | ||
4364 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | ||
4365 | LINKMODE_AUTO | LINKRATE_15 | | ||
4366 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120 | | ||
4367 | phy_id); | ||
4368 | |||
3947 | /* SSC Disable and SAS Analog ST configuration */ | 4369 | /* SSC Disable and SAS Analog ST configuration */ |
3948 | /** | 4370 | /** |
3949 | payload.ase_sh_lm_slr_phyid = | 4371 | payload.ase_sh_lm_slr_phyid = |
@@ -4102,6 +4524,45 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) | |||
4102 | return IRQ_HANDLED; | 4524 | return IRQ_HANDLED; |
4103 | } | 4525 | } |
4104 | 4526 | ||
4527 | void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, | ||
4528 | u32 operation, u32 phyid, u32 length, u32 *buf) | ||
4529 | { | ||
4530 | u32 tag , i, j = 0; | ||
4531 | int rc; | ||
4532 | struct set_phy_profile_req payload; | ||
4533 | struct inbound_queue_table *circularQ; | ||
4534 | u32 opc = OPC_INB_SET_PHY_PROFILE; | ||
4535 | |||
4536 | memset(&payload, 0, sizeof(payload)); | ||
4537 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
4538 | if (rc) | ||
4539 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n")); | ||
4540 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
4541 | payload.tag = cpu_to_le32(tag); | ||
4542 | payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF)); | ||
4543 | PM8001_INIT_DBG(pm8001_ha, | ||
4544 | pm8001_printk(" phy profile command for phy %x ,length is %d\n", | ||
4545 | payload.ppc_phyid, length)); | ||
4546 | for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { | ||
4547 | payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); | ||
4548 | j++; | ||
4549 | } | ||
4550 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
4551 | } | ||
4552 | |||
4553 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | ||
4554 | u32 length, u8 *buf) | ||
4555 | { | ||
4556 | u32 page_code, i; | ||
4557 | |||
4558 | page_code = SAS_PHY_ANALOG_SETTINGS_PAGE; | ||
4559 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
4560 | mpi_set_phy_profile_req(pm8001_ha, | ||
4561 | SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); | ||
4562 | length = length + PHY_DWORD_LENGTH; | ||
4563 | } | ||
4564 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | ||
4565 | } | ||
4105 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4566 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
4106 | .name = "pmc80xx", | 4567 | .name = "pmc80xx", |
4107 | .chip_init = pm80xx_chip_init, | 4568 | .chip_init = pm80xx_chip_init, |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index 2b760ba75d7b..c86816bea424 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
@@ -168,6 +168,11 @@ | |||
168 | #define LINKRATE_15 (0x01 << 8) | 168 | #define LINKRATE_15 (0x01 << 8) |
169 | #define LINKRATE_30 (0x02 << 8) | 169 | #define LINKRATE_30 (0x02 << 8) |
170 | #define LINKRATE_60 (0x06 << 8) | 170 | #define LINKRATE_60 (0x06 << 8) |
171 | #define LINKRATE_120 (0x08 << 8) | ||
172 | |||
173 | /* phy_profile */ | ||
174 | #define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04 | ||
175 | #define PHY_DWORD_LENGTH 0xC | ||
171 | 176 | ||
172 | /* Thermal related */ | 177 | /* Thermal related */ |
173 | #define THERMAL_ENABLE 0x1 | 178 | #define THERMAL_ENABLE 0x1 |
@@ -1223,10 +1228,10 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | |||
1223 | 1228 | ||
1224 | /* MSGU CONFIGURATION TABLE*/ | 1229 | /* MSGU CONFIGURATION TABLE*/ |
1225 | 1230 | ||
1226 | #define SPCv_MSGU_CFG_TABLE_UPDATE 0x01 | 1231 | #define SPCv_MSGU_CFG_TABLE_UPDATE 0x001 |
1227 | #define SPCv_MSGU_CFG_TABLE_RESET 0x02 | 1232 | #define SPCv_MSGU_CFG_TABLE_RESET 0x002 |
1228 | #define SPCv_MSGU_CFG_TABLE_FREEZE 0x04 | 1233 | #define SPCv_MSGU_CFG_TABLE_FREEZE 0x004 |
1229 | #define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x08 | 1234 | #define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x008 |
1230 | #define MSGU_IBDB_SET 0x00 | 1235 | #define MSGU_IBDB_SET 0x00 |
1231 | #define MSGU_HOST_INT_STATUS 0x08 | 1236 | #define MSGU_HOST_INT_STATUS 0x08 |
1232 | #define MSGU_HOST_INT_MASK 0x0C | 1237 | #define MSGU_HOST_INT_MASK 0x0C |
@@ -1520,4 +1525,6 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | |||
1520 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 | 1525 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 |
1521 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 | 1526 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 |
1522 | 1527 | ||
1528 | |||
1529 | #define MEMBASE_II_SHIFT_REGISTER 0x1010 | ||
1523 | #endif | 1530 | #endif |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 41327d46ecf5..084d1fd59c9e 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -306,6 +306,7 @@ struct ddb_entry { | |||
306 | struct qla_ddb_index { | 306 | struct qla_ddb_index { |
307 | struct list_head list; | 307 | struct list_head list; |
308 | uint16_t fw_ddb_idx; | 308 | uint16_t fw_ddb_idx; |
309 | uint16_t flash_ddb_idx; | ||
309 | struct dev_db_entry fw_ddb; | 310 | struct dev_db_entry fw_ddb; |
310 | uint8_t flash_isid[6]; | 311 | uint8_t flash_isid[6]; |
311 | }; | 312 | }; |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 51d1a70f8b45..1243e5942b76 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -539,6 +539,10 @@ struct qla_flt_region { | |||
539 | #define ENABLE_INTERNAL_LOOPBACK 0x04 | 539 | #define ENABLE_INTERNAL_LOOPBACK 0x04 |
540 | #define ENABLE_EXTERNAL_LOOPBACK 0x08 | 540 | #define ENABLE_EXTERNAL_LOOPBACK 0x08 |
541 | 541 | ||
542 | /* generic defines to enable/disable params */ | ||
543 | #define QL4_PARAM_DISABLE 0 | ||
544 | #define QL4_PARAM_ENABLE 1 | ||
545 | |||
542 | /*************************************************************************/ | 546 | /*************************************************************************/ |
543 | 547 | ||
544 | /* Host Adapter Initialization Control Block (from host) */ | 548 | /* Host Adapter Initialization Control Block (from host) */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index e6f2a2669dbd..5cef2527180a 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -83,6 +83,8 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
83 | uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); | 83 | uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); |
84 | int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, | 84 | int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, |
85 | char *password, int bidi, uint16_t *chap_index); | 85 | char *password, int bidi, uint16_t *chap_index); |
86 | int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, | ||
87 | uint16_t idx, int bidi); | ||
86 | 88 | ||
87 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha); | 89 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha); |
88 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha); | 90 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha); |
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 8503ad643bdd..655b7bb644d9 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h | |||
@@ -82,3 +82,15 @@ qla4xxx_disable_intrs(struct scsi_qla_host *ha) | |||
82 | __qla4xxx_disable_intrs(ha); | 82 | __qla4xxx_disable_intrs(ha); |
83 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 83 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
84 | } | 84 | } |
85 | |||
86 | static inline int qla4xxx_get_chap_type(struct ql4_chap_table *chap_entry) | ||
87 | { | ||
88 | int type; | ||
89 | |||
90 | if (chap_entry->flags & BIT_7) | ||
91 | type = LOCAL_CHAP; | ||
92 | else | ||
93 | type = BIDI_CHAP; | ||
94 | |||
95 | return type; | ||
96 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 62d4208af21f..22cbd005bdf4 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -1530,13 +1530,26 @@ exit_get_chap: | |||
1530 | return ret; | 1530 | return ret; |
1531 | } | 1531 | } |
1532 | 1532 | ||
1533 | static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, | 1533 | /** |
1534 | char *password, uint16_t idx, int bidi) | 1534 | * qla4xxx_set_chap - Make a chap entry at the given index |
1535 | * @ha: pointer to adapter structure | ||
1536 | * @username: CHAP username to set | ||
1537 | * @password: CHAP password to set | ||
1538 | * @idx: CHAP index at which to make the entry | ||
1539 | * @bidi: type of chap entry (chap_in or chap_out) | ||
1540 | * | ||
1541 | * Create chap entry at the given index with the information provided. | ||
1542 | * | ||
1543 | * Note: Caller should acquire the chap lock before getting here. | ||
1544 | **/ | ||
1545 | int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, | ||
1546 | uint16_t idx, int bidi) | ||
1535 | { | 1547 | { |
1536 | int ret = 0; | 1548 | int ret = 0; |
1537 | int rval = QLA_ERROR; | 1549 | int rval = QLA_ERROR; |
1538 | uint32_t offset = 0; | 1550 | uint32_t offset = 0; |
1539 | struct ql4_chap_table *chap_table; | 1551 | struct ql4_chap_table *chap_table; |
1552 | uint32_t chap_size = 0; | ||
1540 | dma_addr_t chap_dma; | 1553 | dma_addr_t chap_dma; |
1541 | 1554 | ||
1542 | chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); | 1555 | chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); |
@@ -1554,7 +1567,20 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, | |||
1554 | strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN); | 1567 | strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN); |
1555 | strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN); | 1568 | strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN); |
1556 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); | 1569 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); |
1557 | offset = FLASH_CHAP_OFFSET | (idx * sizeof(struct ql4_chap_table)); | 1570 | |
1571 | if (is_qla40XX(ha)) { | ||
1572 | chap_size = MAX_CHAP_ENTRIES_40XX * sizeof(*chap_table); | ||
1573 | offset = FLASH_CHAP_OFFSET; | ||
1574 | } else { /* Single region contains CHAP info for both ports which is | ||
1575 | * divided into half for each port. | ||
1576 | */ | ||
1577 | chap_size = ha->hw.flt_chap_size / 2; | ||
1578 | offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); | ||
1579 | if (ha->port_num == 1) | ||
1580 | offset += chap_size; | ||
1581 | } | ||
1582 | |||
1583 | offset += (idx * sizeof(struct ql4_chap_table)); | ||
1558 | rval = qla4xxx_set_flash(ha, chap_dma, offset, | 1584 | rval = qla4xxx_set_flash(ha, chap_dma, offset, |
1559 | sizeof(struct ql4_chap_table), | 1585 | sizeof(struct ql4_chap_table), |
1560 | FLASH_OPT_RMW_COMMIT); | 1586 | FLASH_OPT_RMW_COMMIT); |
@@ -1611,7 +1637,7 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, | |||
1611 | goto exit_unlock_uni_chap; | 1637 | goto exit_unlock_uni_chap; |
1612 | } | 1638 | } |
1613 | 1639 | ||
1614 | if (!(chap_table->flags & BIT_6)) { | 1640 | if (!(chap_table->flags & BIT_7)) { |
1615 | ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); | 1641 | ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); |
1616 | rval = QLA_ERROR; | 1642 | rval = QLA_ERROR; |
1617 | goto exit_unlock_uni_chap; | 1643 | goto exit_unlock_uni_chap; |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index f8a0a26a3cd4..6dc3e99b7f9c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -149,6 +149,8 @@ static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, | |||
149 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | 149 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, |
150 | uint32_t *num_entries, char *buf); | 150 | uint32_t *num_entries, char *buf); |
151 | static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); | 151 | static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); |
152 | static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, | ||
153 | int len); | ||
152 | 154 | ||
153 | /* | 155 | /* |
154 | * SCSI host template entry points | 156 | * SCSI host template entry points |
@@ -252,6 +254,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
252 | .send_ping = qla4xxx_send_ping, | 254 | .send_ping = qla4xxx_send_ping, |
253 | .get_chap = qla4xxx_get_chap_list, | 255 | .get_chap = qla4xxx_get_chap_list, |
254 | .delete_chap = qla4xxx_delete_chap, | 256 | .delete_chap = qla4xxx_delete_chap, |
257 | .set_chap = qla4xxx_set_chap_entry, | ||
255 | .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, | 258 | .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, |
256 | .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, | 259 | .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, |
257 | .new_flashnode = qla4xxx_sysfs_ddb_add, | 260 | .new_flashnode = qla4xxx_sysfs_ddb_add, |
@@ -508,6 +511,95 @@ static umode_t qla4_attr_is_visible(int param_type, int param) | |||
508 | return 0; | 511 | return 0; |
509 | } | 512 | } |
510 | 513 | ||
514 | static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, | ||
515 | int16_t chap_index, | ||
516 | struct ql4_chap_table **chap_entry) | ||
517 | { | ||
518 | int rval = QLA_ERROR; | ||
519 | int max_chap_entries; | ||
520 | |||
521 | if (!ha->chap_list) { | ||
522 | ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); | ||
523 | rval = QLA_ERROR; | ||
524 | goto exit_get_chap; | ||
525 | } | ||
526 | |||
527 | if (is_qla80XX(ha)) | ||
528 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
529 | sizeof(struct ql4_chap_table); | ||
530 | else | ||
531 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
532 | |||
533 | if (chap_index > max_chap_entries) { | ||
534 | ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); | ||
535 | rval = QLA_ERROR; | ||
536 | goto exit_get_chap; | ||
537 | } | ||
538 | |||
539 | *chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index; | ||
540 | if ((*chap_entry)->cookie != | ||
541 | __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { | ||
542 | rval = QLA_ERROR; | ||
543 | *chap_entry = NULL; | ||
544 | } else { | ||
545 | rval = QLA_SUCCESS; | ||
546 | } | ||
547 | |||
548 | exit_get_chap: | ||
549 | return rval; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * qla4xxx_find_free_chap_index - Find the first free chap index | ||
554 | * @ha: pointer to adapter structure | ||
555 | * @chap_index: CHAP index to be returned | ||
556 | * | ||
557 | * Find the first free chap index available in the chap table | ||
558 | * | ||
559 | * Note: Caller should acquire the chap lock before getting here. | ||
560 | **/ | ||
561 | static int qla4xxx_find_free_chap_index(struct scsi_qla_host *ha, | ||
562 | uint16_t *chap_index) | ||
563 | { | ||
564 | int i, rval; | ||
565 | int free_index = -1; | ||
566 | int max_chap_entries = 0; | ||
567 | struct ql4_chap_table *chap_table; | ||
568 | |||
569 | if (is_qla80XX(ha)) | ||
570 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
571 | sizeof(struct ql4_chap_table); | ||
572 | else | ||
573 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
574 | |||
575 | if (!ha->chap_list) { | ||
576 | ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); | ||
577 | rval = QLA_ERROR; | ||
578 | goto exit_find_chap; | ||
579 | } | ||
580 | |||
581 | for (i = 0; i < max_chap_entries; i++) { | ||
582 | chap_table = (struct ql4_chap_table *)ha->chap_list + i; | ||
583 | |||
584 | if ((chap_table->cookie != | ||
585 | __constant_cpu_to_le16(CHAP_VALID_COOKIE)) && | ||
586 | (i > MAX_RESRV_CHAP_IDX)) { | ||
587 | free_index = i; | ||
588 | break; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | if (free_index != -1) { | ||
593 | *chap_index = free_index; | ||
594 | rval = QLA_SUCCESS; | ||
595 | } else { | ||
596 | rval = QLA_ERROR; | ||
597 | } | ||
598 | |||
599 | exit_find_chap: | ||
600 | return rval; | ||
601 | } | ||
602 | |||
511 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | 603 | static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, |
512 | uint32_t *num_entries, char *buf) | 604 | uint32_t *num_entries, char *buf) |
513 | { | 605 | { |
@@ -691,6 +783,111 @@ exit_delete_chap: | |||
691 | return ret; | 783 | return ret; |
692 | } | 784 | } |
693 | 785 | ||
786 | /** | ||
787 | * qla4xxx_set_chap_entry - Make chap entry with given information | ||
788 | * @shost: pointer to host | ||
789 | * @data: chap info - credentials, index and type to make chap entry | ||
790 | * @len: length of data | ||
791 | * | ||
792 | * Add or update chap entry with the given information | ||
793 | **/ | ||
794 | static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) | ||
795 | { | ||
796 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
797 | struct iscsi_chap_rec chap_rec; | ||
798 | struct ql4_chap_table *chap_entry = NULL; | ||
799 | struct iscsi_param_info *param_info; | ||
800 | struct nlattr *attr; | ||
801 | int max_chap_entries = 0; | ||
802 | int type; | ||
803 | int rem = len; | ||
804 | int rc = 0; | ||
805 | |||
806 | memset(&chap_rec, 0, sizeof(chap_rec)); | ||
807 | |||
808 | nla_for_each_attr(attr, data, len, rem) { | ||
809 | param_info = nla_data(attr); | ||
810 | |||
811 | switch (param_info->param) { | ||
812 | case ISCSI_CHAP_PARAM_INDEX: | ||
813 | chap_rec.chap_tbl_idx = *(uint16_t *)param_info->value; | ||
814 | break; | ||
815 | case ISCSI_CHAP_PARAM_CHAP_TYPE: | ||
816 | chap_rec.chap_type = param_info->value[0]; | ||
817 | break; | ||
818 | case ISCSI_CHAP_PARAM_USERNAME: | ||
819 | memcpy(chap_rec.username, param_info->value, | ||
820 | param_info->len); | ||
821 | break; | ||
822 | case ISCSI_CHAP_PARAM_PASSWORD: | ||
823 | memcpy(chap_rec.password, param_info->value, | ||
824 | param_info->len); | ||
825 | break; | ||
826 | case ISCSI_CHAP_PARAM_PASSWORD_LEN: | ||
827 | chap_rec.password_length = param_info->value[0]; | ||
828 | break; | ||
829 | default: | ||
830 | ql4_printk(KERN_ERR, ha, | ||
831 | "%s: No such sysfs attribute\n", __func__); | ||
832 | rc = -ENOSYS; | ||
833 | goto exit_set_chap; | ||
834 | }; | ||
835 | } | ||
836 | |||
837 | if (chap_rec.chap_type == CHAP_TYPE_IN) | ||
838 | type = BIDI_CHAP; | ||
839 | else | ||
840 | type = LOCAL_CHAP; | ||
841 | |||
842 | if (is_qla80XX(ha)) | ||
843 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
844 | sizeof(struct ql4_chap_table); | ||
845 | else | ||
846 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
847 | |||
848 | mutex_lock(&ha->chap_sem); | ||
849 | if (chap_rec.chap_tbl_idx < max_chap_entries) { | ||
850 | rc = qla4xxx_get_chap_by_index(ha, chap_rec.chap_tbl_idx, | ||
851 | &chap_entry); | ||
852 | if (!rc) { | ||
853 | if (!(type == qla4xxx_get_chap_type(chap_entry))) { | ||
854 | ql4_printk(KERN_INFO, ha, | ||
855 | "Type mismatch for CHAP entry %d\n", | ||
856 | chap_rec.chap_tbl_idx); | ||
857 | rc = -EINVAL; | ||
858 | goto exit_unlock_chap; | ||
859 | } | ||
860 | |||
861 | /* If chap index is in use then don't modify it */ | ||
862 | rc = qla4xxx_is_chap_active(shost, | ||
863 | chap_rec.chap_tbl_idx); | ||
864 | if (rc) { | ||
865 | ql4_printk(KERN_INFO, ha, | ||
866 | "CHAP entry %d is in use\n", | ||
867 | chap_rec.chap_tbl_idx); | ||
868 | rc = -EBUSY; | ||
869 | goto exit_unlock_chap; | ||
870 | } | ||
871 | } | ||
872 | } else { | ||
873 | rc = qla4xxx_find_free_chap_index(ha, &chap_rec.chap_tbl_idx); | ||
874 | if (rc) { | ||
875 | ql4_printk(KERN_INFO, ha, "CHAP entry not available\n"); | ||
876 | rc = -EBUSY; | ||
877 | goto exit_unlock_chap; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | rc = qla4xxx_set_chap(ha, chap_rec.username, chap_rec.password, | ||
882 | chap_rec.chap_tbl_idx, type); | ||
883 | |||
884 | exit_unlock_chap: | ||
885 | mutex_unlock(&ha->chap_sem); | ||
886 | |||
887 | exit_set_chap: | ||
888 | return rc; | ||
889 | } | ||
890 | |||
694 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, | 891 | static int qla4xxx_get_iface_param(struct iscsi_iface *iface, |
695 | enum iscsi_param_type param_type, | 892 | enum iscsi_param_type param_type, |
696 | int param, char *buf) | 893 | int param, char *buf) |
@@ -1455,9 +1652,12 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, | |||
1455 | struct iscsi_session *sess = cls_sess->dd_data; | 1652 | struct iscsi_session *sess = cls_sess->dd_data; |
1456 | struct ddb_entry *ddb_entry = sess->dd_data; | 1653 | struct ddb_entry *ddb_entry = sess->dd_data; |
1457 | struct scsi_qla_host *ha = ddb_entry->ha; | 1654 | struct scsi_qla_host *ha = ddb_entry->ha; |
1655 | struct iscsi_cls_conn *cls_conn = ddb_entry->conn; | ||
1656 | struct ql4_chap_table chap_tbl; | ||
1458 | int rval, len; | 1657 | int rval, len; |
1459 | uint16_t idx; | 1658 | uint16_t idx; |
1460 | 1659 | ||
1660 | memset(&chap_tbl, 0, sizeof(chap_tbl)); | ||
1461 | switch (param) { | 1661 | switch (param) { |
1462 | case ISCSI_PARAM_CHAP_IN_IDX: | 1662 | case ISCSI_PARAM_CHAP_IN_IDX: |
1463 | rval = qla4xxx_get_chap_index(ha, sess->username_in, | 1663 | rval = qla4xxx_get_chap_index(ha, sess->username_in, |
@@ -1469,14 +1669,46 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, | |||
1469 | len = sprintf(buf, "%hu\n", idx); | 1669 | len = sprintf(buf, "%hu\n", idx); |
1470 | break; | 1670 | break; |
1471 | case ISCSI_PARAM_CHAP_OUT_IDX: | 1671 | case ISCSI_PARAM_CHAP_OUT_IDX: |
1472 | rval = qla4xxx_get_chap_index(ha, sess->username, | 1672 | if (ddb_entry->ddb_type == FLASH_DDB) { |
1473 | sess->password, LOCAL_CHAP, | 1673 | if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { |
1474 | &idx); | 1674 | idx = ddb_entry->chap_tbl_idx; |
1675 | rval = QLA_SUCCESS; | ||
1676 | } else { | ||
1677 | rval = QLA_ERROR; | ||
1678 | } | ||
1679 | } else { | ||
1680 | rval = qla4xxx_get_chap_index(ha, sess->username, | ||
1681 | sess->password, | ||
1682 | LOCAL_CHAP, &idx); | ||
1683 | } | ||
1475 | if (rval) | 1684 | if (rval) |
1476 | len = sprintf(buf, "\n"); | 1685 | len = sprintf(buf, "\n"); |
1477 | else | 1686 | else |
1478 | len = sprintf(buf, "%hu\n", idx); | 1687 | len = sprintf(buf, "%hu\n", idx); |
1479 | break; | 1688 | break; |
1689 | case ISCSI_PARAM_USERNAME: | ||
1690 | case ISCSI_PARAM_PASSWORD: | ||
1691 | /* First, populate session username and password for FLASH DDB, | ||
1692 | * if not already done. This happens when session login fails | ||
1693 | * for a FLASH DDB. | ||
1694 | */ | ||
1695 | if (ddb_entry->ddb_type == FLASH_DDB && | ||
1696 | ddb_entry->chap_tbl_idx != INVALID_ENTRY && | ||
1697 | !sess->username && !sess->password) { | ||
1698 | idx = ddb_entry->chap_tbl_idx; | ||
1699 | rval = qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, | ||
1700 | chap_tbl.secret, | ||
1701 | idx); | ||
1702 | if (!rval) { | ||
1703 | iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, | ||
1704 | (char *)chap_tbl.name, | ||
1705 | strlen((char *)chap_tbl.name)); | ||
1706 | iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, | ||
1707 | (char *)chap_tbl.secret, | ||
1708 | chap_tbl.secret_len); | ||
1709 | } | ||
1710 | } | ||
1711 | /* allow fall-through */ | ||
1480 | default: | 1712 | default: |
1481 | return iscsi_session_get_param(cls_sess, param, buf); | 1713 | return iscsi_session_get_param(cls_sess, param, buf); |
1482 | } | 1714 | } |
@@ -2373,11 +2605,6 @@ static void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn, | |||
2373 | COPY_ISID(sess->isid, fw_ddb_entry->isid); | 2605 | COPY_ISID(sess->isid, fw_ddb_entry->isid); |
2374 | 2606 | ||
2375 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | 2607 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); |
2376 | if (ddb_link < MAX_DDB_ENTRIES) | ||
2377 | sess->discovery_parent_idx = ddb_link; | ||
2378 | else | ||
2379 | sess->discovery_parent_idx = DDB_NO_LINK; | ||
2380 | |||
2381 | if (ddb_link == DDB_ISNS) | 2608 | if (ddb_link == DDB_ISNS) |
2382 | disc_parent = ISCSI_DISC_PARENT_ISNS; | 2609 | disc_parent = ISCSI_DISC_PARENT_ISNS; |
2383 | else if (ddb_link == DDB_NO_LINK) | 2610 | else if (ddb_link == DDB_NO_LINK) |
@@ -2402,6 +2629,7 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2402 | int buflen = 0; | 2629 | int buflen = 0; |
2403 | struct iscsi_session *sess; | 2630 | struct iscsi_session *sess; |
2404 | struct ddb_entry *ddb_entry; | 2631 | struct ddb_entry *ddb_entry; |
2632 | struct ql4_chap_table chap_tbl; | ||
2405 | struct iscsi_conn *conn; | 2633 | struct iscsi_conn *conn; |
2406 | char ip_addr[DDB_IPADDR_LEN]; | 2634 | char ip_addr[DDB_IPADDR_LEN]; |
2407 | uint16_t options = 0; | 2635 | uint16_t options = 0; |
@@ -2409,6 +2637,7 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2409 | sess = cls_sess->dd_data; | 2637 | sess = cls_sess->dd_data; |
2410 | ddb_entry = sess->dd_data; | 2638 | ddb_entry = sess->dd_data; |
2411 | conn = cls_conn->dd_data; | 2639 | conn = cls_conn->dd_data; |
2640 | memset(&chap_tbl, 0, sizeof(chap_tbl)); | ||
2412 | 2641 | ||
2413 | ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); | 2642 | ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); |
2414 | 2643 | ||
@@ -2435,6 +2664,19 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | |||
2435 | (char *)fw_ddb_entry->iscsi_name, buflen); | 2664 | (char *)fw_ddb_entry->iscsi_name, buflen); |
2436 | iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, | 2665 | iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, |
2437 | (char *)ha->name_string, buflen); | 2666 | (char *)ha->name_string, buflen); |
2667 | |||
2668 | if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { | ||
2669 | if (!qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, | ||
2670 | chap_tbl.secret, | ||
2671 | ddb_entry->chap_tbl_idx)) { | ||
2672 | iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, | ||
2673 | (char *)chap_tbl.name, | ||
2674 | strlen((char *)chap_tbl.name)); | ||
2675 | iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, | ||
2676 | (char *)chap_tbl.secret, | ||
2677 | chap_tbl.secret_len); | ||
2678 | } | ||
2679 | } | ||
2438 | } | 2680 | } |
2439 | 2681 | ||
2440 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, | 2682 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, |
@@ -4937,7 +5179,8 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, | |||
4937 | } | 5179 | } |
4938 | 5180 | ||
4939 | static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, | 5181 | static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, |
4940 | struct dev_db_entry *fw_ddb_entry) | 5182 | struct dev_db_entry *fw_ddb_entry, |
5183 | uint32_t *index) | ||
4941 | { | 5184 | { |
4942 | struct ddb_entry *ddb_entry; | 5185 | struct ddb_entry *ddb_entry; |
4943 | struct ql4_tuple_ddb *fw_tddb = NULL; | 5186 | struct ql4_tuple_ddb *fw_tddb = NULL; |
@@ -4971,6 +5214,8 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, | |||
4971 | qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); | 5214 | qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); |
4972 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) { | 5215 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) { |
4973 | ret = QLA_SUCCESS; /* found */ | 5216 | ret = QLA_SUCCESS; /* found */ |
5217 | if (index != NULL) | ||
5218 | *index = idx; | ||
4974 | goto exit_check; | 5219 | goto exit_check; |
4975 | } | 5220 | } |
4976 | } | 5221 | } |
@@ -5206,6 +5451,7 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, | |||
5206 | ddb_entry->ha = ha; | 5451 | ddb_entry->ha = ha; |
5207 | ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; | 5452 | ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; |
5208 | ddb_entry->ddb_change = qla4xxx_flash_ddb_change; | 5453 | ddb_entry->ddb_change = qla4xxx_flash_ddb_change; |
5454 | ddb_entry->chap_tbl_idx = INVALID_ENTRY; | ||
5209 | 5455 | ||
5210 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); | 5456 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); |
5211 | atomic_set(&ddb_entry->relogin_timer, 0); | 5457 | atomic_set(&ddb_entry->relogin_timer, 0); |
@@ -5267,6 +5513,87 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) | |||
5267 | } while (time_after(wtime, jiffies)); | 5513 | } while (time_after(wtime, jiffies)); |
5268 | } | 5514 | } |
5269 | 5515 | ||
5516 | static int qla4xxx_cmp_fw_stentry(struct dev_db_entry *fw_ddb_entry, | ||
5517 | struct dev_db_entry *flash_ddb_entry) | ||
5518 | { | ||
5519 | uint16_t options = 0; | ||
5520 | size_t ip_len = IP_ADDR_LEN; | ||
5521 | |||
5522 | options = le16_to_cpu(fw_ddb_entry->options); | ||
5523 | if (options & DDB_OPT_IPV6_DEVICE) | ||
5524 | ip_len = IPv6_ADDR_LEN; | ||
5525 | |||
5526 | if (memcmp(fw_ddb_entry->ip_addr, flash_ddb_entry->ip_addr, ip_len)) | ||
5527 | return QLA_ERROR; | ||
5528 | |||
5529 | if (memcmp(&fw_ddb_entry->isid[0], &flash_ddb_entry->isid[0], | ||
5530 | sizeof(fw_ddb_entry->isid))) | ||
5531 | return QLA_ERROR; | ||
5532 | |||
5533 | if (memcmp(&fw_ddb_entry->port, &flash_ddb_entry->port, | ||
5534 | sizeof(fw_ddb_entry->port))) | ||
5535 | return QLA_ERROR; | ||
5536 | |||
5537 | return QLA_SUCCESS; | ||
5538 | } | ||
5539 | |||
5540 | static int qla4xxx_find_flash_st_idx(struct scsi_qla_host *ha, | ||
5541 | struct dev_db_entry *fw_ddb_entry, | ||
5542 | uint32_t fw_idx, uint32_t *flash_index) | ||
5543 | { | ||
5544 | struct dev_db_entry *flash_ddb_entry; | ||
5545 | dma_addr_t flash_ddb_entry_dma; | ||
5546 | uint32_t idx = 0; | ||
5547 | int max_ddbs; | ||
5548 | int ret = QLA_ERROR, status; | ||
5549 | |||
5550 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5551 | MAX_DEV_DB_ENTRIES; | ||
5552 | |||
5553 | flash_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
5554 | &flash_ddb_entry_dma); | ||
5555 | if (flash_ddb_entry == NULL || fw_ddb_entry == NULL) { | ||
5556 | ql4_printk(KERN_ERR, ha, "Out of memory\n"); | ||
5557 | goto exit_find_st_idx; | ||
5558 | } | ||
5559 | |||
5560 | status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, | ||
5561 | flash_ddb_entry_dma, fw_idx); | ||
5562 | if (status == QLA_SUCCESS) { | ||
5563 | status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); | ||
5564 | if (status == QLA_SUCCESS) { | ||
5565 | *flash_index = fw_idx; | ||
5566 | ret = QLA_SUCCESS; | ||
5567 | goto exit_find_st_idx; | ||
5568 | } | ||
5569 | } | ||
5570 | |||
5571 | for (idx = 0; idx < max_ddbs; idx++) { | ||
5572 | status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, | ||
5573 | flash_ddb_entry_dma, idx); | ||
5574 | if (status == QLA_ERROR) | ||
5575 | continue; | ||
5576 | |||
5577 | status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); | ||
5578 | if (status == QLA_SUCCESS) { | ||
5579 | *flash_index = idx; | ||
5580 | ret = QLA_SUCCESS; | ||
5581 | goto exit_find_st_idx; | ||
5582 | } | ||
5583 | } | ||
5584 | |||
5585 | if (idx == max_ddbs) | ||
5586 | ql4_printk(KERN_ERR, ha, "Failed to find ST [%d] in flash\n", | ||
5587 | fw_idx); | ||
5588 | |||
5589 | exit_find_st_idx: | ||
5590 | if (flash_ddb_entry) | ||
5591 | dma_pool_free(ha->fw_ddb_dma_pool, flash_ddb_entry, | ||
5592 | flash_ddb_entry_dma); | ||
5593 | |||
5594 | return ret; | ||
5595 | } | ||
5596 | |||
5270 | static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | 5597 | static void qla4xxx_build_st_list(struct scsi_qla_host *ha, |
5271 | struct list_head *list_st) | 5598 | struct list_head *list_st) |
5272 | { | 5599 | { |
@@ -5278,6 +5605,7 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | |||
5278 | int ret; | 5605 | int ret; |
5279 | uint32_t idx = 0, next_idx = 0; | 5606 | uint32_t idx = 0, next_idx = 0; |
5280 | uint32_t state = 0, conn_err = 0; | 5607 | uint32_t state = 0, conn_err = 0; |
5608 | uint32_t flash_index = -1; | ||
5281 | uint16_t conn_id = 0; | 5609 | uint16_t conn_id = 0; |
5282 | 5610 | ||
5283 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | 5611 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, |
@@ -5310,6 +5638,19 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha, | |||
5310 | if (!st_ddb_idx) | 5638 | if (!st_ddb_idx) |
5311 | break; | 5639 | break; |
5312 | 5640 | ||
5641 | ret = qla4xxx_find_flash_st_idx(ha, fw_ddb_entry, idx, | ||
5642 | &flash_index); | ||
5643 | if (ret == QLA_ERROR) { | ||
5644 | ql4_printk(KERN_ERR, ha, | ||
5645 | "No flash entry for ST at idx [%d]\n", idx); | ||
5646 | st_ddb_idx->flash_ddb_idx = idx; | ||
5647 | } else { | ||
5648 | ql4_printk(KERN_INFO, ha, | ||
5649 | "ST at idx [%d] is stored at flash [%d]\n", | ||
5650 | idx, flash_index); | ||
5651 | st_ddb_idx->flash_ddb_idx = flash_index; | ||
5652 | } | ||
5653 | |||
5313 | st_ddb_idx->fw_ddb_idx = idx; | 5654 | st_ddb_idx->fw_ddb_idx = idx; |
5314 | 5655 | ||
5315 | list_add_tail(&st_ddb_idx->list, list_st); | 5656 | list_add_tail(&st_ddb_idx->list, list_st); |
@@ -5354,6 +5695,28 @@ static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha, | |||
5354 | } | 5695 | } |
5355 | } | 5696 | } |
5356 | 5697 | ||
5698 | static void qla4xxx_update_sess_disc_idx(struct scsi_qla_host *ha, | ||
5699 | struct ddb_entry *ddb_entry, | ||
5700 | struct dev_db_entry *fw_ddb_entry) | ||
5701 | { | ||
5702 | struct iscsi_cls_session *cls_sess; | ||
5703 | struct iscsi_session *sess; | ||
5704 | uint32_t max_ddbs = 0; | ||
5705 | uint16_t ddb_link = -1; | ||
5706 | |||
5707 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5708 | MAX_DEV_DB_ENTRIES; | ||
5709 | |||
5710 | cls_sess = ddb_entry->sess; | ||
5711 | sess = cls_sess->dd_data; | ||
5712 | |||
5713 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5714 | if (ddb_link < max_ddbs) | ||
5715 | sess->discovery_parent_idx = ddb_link; | ||
5716 | else | ||
5717 | sess->discovery_parent_idx = DDB_NO_LINK; | ||
5718 | } | ||
5719 | |||
5357 | static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, | 5720 | static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, |
5358 | struct dev_db_entry *fw_ddb_entry, | 5721 | struct dev_db_entry *fw_ddb_entry, |
5359 | int is_reset, uint16_t idx) | 5722 | int is_reset, uint16_t idx) |
@@ -5418,6 +5781,7 @@ static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, | |||
5418 | 5781 | ||
5419 | /* Update sess/conn params */ | 5782 | /* Update sess/conn params */ |
5420 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); | 5783 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); |
5784 | qla4xxx_update_sess_disc_idx(ha, ddb_entry, fw_ddb_entry); | ||
5421 | 5785 | ||
5422 | if (is_reset == RESET_ADAPTER) { | 5786 | if (is_reset == RESET_ADAPTER) { |
5423 | iscsi_block_session(cls_sess); | 5787 | iscsi_block_session(cls_sess); |
@@ -5434,17 +5798,43 @@ exit_setup: | |||
5434 | return ret; | 5798 | return ret; |
5435 | } | 5799 | } |
5436 | 5800 | ||
5801 | static void qla4xxx_update_fw_ddb_link(struct scsi_qla_host *ha, | ||
5802 | struct list_head *list_ddb, | ||
5803 | struct dev_db_entry *fw_ddb_entry) | ||
5804 | { | ||
5805 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | ||
5806 | uint16_t ddb_link; | ||
5807 | |||
5808 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5809 | |||
5810 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { | ||
5811 | if (ddb_idx->fw_ddb_idx == ddb_link) { | ||
5812 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5813 | "Updating NT parent idx from [%d] to [%d]\n", | ||
5814 | ddb_link, ddb_idx->flash_ddb_idx)); | ||
5815 | fw_ddb_entry->ddb_link = | ||
5816 | cpu_to_le16(ddb_idx->flash_ddb_idx); | ||
5817 | return; | ||
5818 | } | ||
5819 | } | ||
5820 | } | ||
5821 | |||
5437 | static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | 5822 | static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, |
5438 | struct list_head *list_nt, int is_reset) | 5823 | struct list_head *list_nt, |
5824 | struct list_head *list_st, | ||
5825 | int is_reset) | ||
5439 | { | 5826 | { |
5440 | struct dev_db_entry *fw_ddb_entry; | 5827 | struct dev_db_entry *fw_ddb_entry; |
5828 | struct ddb_entry *ddb_entry = NULL; | ||
5441 | dma_addr_t fw_ddb_dma; | 5829 | dma_addr_t fw_ddb_dma; |
5442 | int max_ddbs; | 5830 | int max_ddbs; |
5443 | int fw_idx_size; | 5831 | int fw_idx_size; |
5444 | int ret; | 5832 | int ret; |
5445 | uint32_t idx = 0, next_idx = 0; | 5833 | uint32_t idx = 0, next_idx = 0; |
5446 | uint32_t state = 0, conn_err = 0; | 5834 | uint32_t state = 0, conn_err = 0; |
5835 | uint32_t ddb_idx = -1; | ||
5447 | uint16_t conn_id = 0; | 5836 | uint16_t conn_id = 0; |
5837 | uint16_t ddb_link = -1; | ||
5448 | struct qla_ddb_index *nt_ddb_idx; | 5838 | struct qla_ddb_index *nt_ddb_idx; |
5449 | 5839 | ||
5450 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | 5840 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, |
@@ -5471,12 +5861,18 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | |||
5471 | if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) | 5861 | if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) |
5472 | goto continue_next_nt; | 5862 | goto continue_next_nt; |
5473 | 5863 | ||
5864 | ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
5865 | if (ddb_link < max_ddbs) | ||
5866 | qla4xxx_update_fw_ddb_link(ha, list_st, fw_ddb_entry); | ||
5867 | |||
5474 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || | 5868 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || |
5475 | state == DDB_DS_SESSION_FAILED)) | 5869 | state == DDB_DS_SESSION_FAILED) && |
5870 | (is_reset == INIT_ADAPTER)) | ||
5476 | goto continue_next_nt; | 5871 | goto continue_next_nt; |
5477 | 5872 | ||
5478 | DEBUG2(ql4_printk(KERN_INFO, ha, | 5873 | DEBUG2(ql4_printk(KERN_INFO, ha, |
5479 | "Adding DDB to session = 0x%x\n", idx)); | 5874 | "Adding DDB to session = 0x%x\n", idx)); |
5875 | |||
5480 | if (is_reset == INIT_ADAPTER) { | 5876 | if (is_reset == INIT_ADAPTER) { |
5481 | nt_ddb_idx = vmalloc(fw_idx_size); | 5877 | nt_ddb_idx = vmalloc(fw_idx_size); |
5482 | if (!nt_ddb_idx) | 5878 | if (!nt_ddb_idx) |
@@ -5506,9 +5902,17 @@ static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, | |||
5506 | 5902 | ||
5507 | list_add_tail(&nt_ddb_idx->list, list_nt); | 5903 | list_add_tail(&nt_ddb_idx->list, list_nt); |
5508 | } else if (is_reset == RESET_ADAPTER) { | 5904 | } else if (is_reset == RESET_ADAPTER) { |
5509 | if (qla4xxx_is_session_exists(ha, fw_ddb_entry) == | 5905 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, |
5510 | QLA_SUCCESS) | 5906 | &ddb_idx); |
5907 | if (ret == QLA_SUCCESS) { | ||
5908 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, | ||
5909 | ddb_idx); | ||
5910 | if (ddb_entry != NULL) | ||
5911 | qla4xxx_update_sess_disc_idx(ha, | ||
5912 | ddb_entry, | ||
5913 | fw_ddb_entry); | ||
5511 | goto continue_next_nt; | 5914 | goto continue_next_nt; |
5915 | } | ||
5512 | } | 5916 | } |
5513 | 5917 | ||
5514 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx); | 5918 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx); |
@@ -5526,7 +5930,8 @@ exit_nt_list: | |||
5526 | } | 5930 | } |
5527 | 5931 | ||
5528 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | 5932 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, |
5529 | struct list_head *list_nt) | 5933 | struct list_head *list_nt, |
5934 | uint16_t target_id) | ||
5530 | { | 5935 | { |
5531 | struct dev_db_entry *fw_ddb_entry; | 5936 | struct dev_db_entry *fw_ddb_entry; |
5532 | dma_addr_t fw_ddb_dma; | 5937 | dma_addr_t fw_ddb_dma; |
@@ -5571,13 +5976,16 @@ static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | |||
5571 | 5976 | ||
5572 | nt_ddb_idx->fw_ddb_idx = idx; | 5977 | nt_ddb_idx->fw_ddb_idx = idx; |
5573 | 5978 | ||
5574 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | 5979 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); |
5575 | if (ret == QLA_SUCCESS) { | 5980 | if (ret == QLA_SUCCESS) { |
5576 | /* free nt_ddb_idx and do not add to list_nt */ | 5981 | /* free nt_ddb_idx and do not add to list_nt */ |
5577 | vfree(nt_ddb_idx); | 5982 | vfree(nt_ddb_idx); |
5578 | goto continue_next_new_nt; | 5983 | goto continue_next_new_nt; |
5579 | } | 5984 | } |
5580 | 5985 | ||
5986 | if (target_id < max_ddbs) | ||
5987 | fw_ddb_entry->ddb_link = cpu_to_le16(target_id); | ||
5988 | |||
5581 | list_add_tail(&nt_ddb_idx->list, list_nt); | 5989 | list_add_tail(&nt_ddb_idx->list, list_nt); |
5582 | 5990 | ||
5583 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | 5991 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, |
@@ -5894,7 +6302,8 @@ exit_ddb_conn_open: | |||
5894 | } | 6302 | } |
5895 | 6303 | ||
5896 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | 6304 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, |
5897 | struct dev_db_entry *fw_ddb_entry) | 6305 | struct dev_db_entry *fw_ddb_entry, |
6306 | uint16_t target_id) | ||
5898 | { | 6307 | { |
5899 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | 6308 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; |
5900 | struct list_head list_nt; | 6309 | struct list_head list_nt; |
@@ -5919,7 +6328,7 @@ static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | |||
5919 | if (ret == QLA_ERROR) | 6328 | if (ret == QLA_ERROR) |
5920 | goto exit_login_st; | 6329 | goto exit_login_st; |
5921 | 6330 | ||
5922 | qla4xxx_build_new_nt_list(ha, &list_nt); | 6331 | qla4xxx_build_new_nt_list(ha, &list_nt, target_id); |
5923 | 6332 | ||
5924 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { | 6333 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { |
5925 | list_del_init(&ddb_idx->list); | 6334 | list_del_init(&ddb_idx->list); |
@@ -5946,7 +6355,7 @@ static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, | |||
5946 | { | 6355 | { |
5947 | int ret = QLA_ERROR; | 6356 | int ret = QLA_ERROR; |
5948 | 6357 | ||
5949 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | 6358 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); |
5950 | if (ret != QLA_SUCCESS) | 6359 | if (ret != QLA_SUCCESS) |
5951 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | 6360 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, |
5952 | idx); | 6361 | idx); |
@@ -6001,7 +6410,8 @@ static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, | |||
6001 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | 6410 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; |
6002 | 6411 | ||
6003 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | 6412 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) |
6004 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry); | 6413 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry, |
6414 | fnode_sess->target_id); | ||
6005 | else | 6415 | else |
6006 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, | 6416 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, |
6007 | fnode_sess->target_id); | 6417 | fnode_sess->target_id); |
@@ -6522,10 +6932,13 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6522 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | 6932 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); |
6523 | struct scsi_qla_host *ha = to_qla_host(shost); | 6933 | struct scsi_qla_host *ha = to_qla_host(shost); |
6524 | struct iscsi_flashnode_param_info *fnode_param; | 6934 | struct iscsi_flashnode_param_info *fnode_param; |
6935 | struct ql4_chap_table chap_tbl; | ||
6525 | struct nlattr *attr; | 6936 | struct nlattr *attr; |
6937 | uint16_t chap_out_idx = INVALID_ENTRY; | ||
6526 | int rc = QLA_ERROR; | 6938 | int rc = QLA_ERROR; |
6527 | uint32_t rem = len; | 6939 | uint32_t rem = len; |
6528 | 6940 | ||
6941 | memset((void *)&chap_tbl, 0, sizeof(chap_tbl)); | ||
6529 | nla_for_each_attr(attr, data, len, rem) { | 6942 | nla_for_each_attr(attr, data, len, rem) { |
6530 | fnode_param = nla_data(attr); | 6943 | fnode_param = nla_data(attr); |
6531 | 6944 | ||
@@ -6567,6 +6980,10 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6567 | break; | 6980 | break; |
6568 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | 6981 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: |
6569 | fnode_sess->chap_auth_en = fnode_param->value[0]; | 6982 | fnode_sess->chap_auth_en = fnode_param->value[0]; |
6983 | /* Invalidate chap index if chap auth is disabled */ | ||
6984 | if (!fnode_sess->chap_auth_en) | ||
6985 | fnode_sess->chap_out_idx = INVALID_ENTRY; | ||
6986 | |||
6570 | break; | 6987 | break; |
6571 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | 6988 | case ISCSI_FLASHNODE_SNACK_REQ_EN: |
6572 | fnode_conn->snack_req_en = fnode_param->value[0]; | 6989 | fnode_conn->snack_req_en = fnode_param->value[0]; |
@@ -6705,6 +7122,17 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
6705 | fnode_conn->exp_statsn = | 7122 | fnode_conn->exp_statsn = |
6706 | *(uint32_t *)fnode_param->value; | 7123 | *(uint32_t *)fnode_param->value; |
6707 | break; | 7124 | break; |
7125 | case ISCSI_FLASHNODE_CHAP_OUT_IDX: | ||
7126 | chap_out_idx = *(uint16_t *)fnode_param->value; | ||
7127 | if (!qla4xxx_get_uni_chap_at_index(ha, | ||
7128 | chap_tbl.name, | ||
7129 | chap_tbl.secret, | ||
7130 | chap_out_idx)) { | ||
7131 | fnode_sess->chap_out_idx = chap_out_idx; | ||
7132 | /* Enable chap auth if chap index is valid */ | ||
7133 | fnode_sess->chap_auth_en = QL4_PARAM_ENABLE; | ||
7134 | } | ||
7135 | break; | ||
6708 | default: | 7136 | default: |
6709 | ql4_printk(KERN_ERR, ha, | 7137 | ql4_printk(KERN_ERR, ha, |
6710 | "%s: No such sysfs attribute\n", __func__); | 7138 | "%s: No such sysfs attribute\n", __func__); |
@@ -6926,11 +7354,10 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) | |||
6926 | schedule_timeout_uninterruptible(HZ / 10); | 7354 | schedule_timeout_uninterruptible(HZ / 10); |
6927 | } while (time_after(wtime, jiffies)); | 7355 | } while (time_after(wtime, jiffies)); |
6928 | 7356 | ||
6929 | /* Free up the sendtargets list */ | ||
6930 | qla4xxx_free_ddb_list(&list_st); | ||
6931 | 7357 | ||
6932 | qla4xxx_build_nt_list(ha, &list_nt, is_reset); | 7358 | qla4xxx_build_nt_list(ha, &list_nt, &list_st, is_reset); |
6933 | 7359 | ||
7360 | qla4xxx_free_ddb_list(&list_st); | ||
6934 | qla4xxx_free_ddb_list(&list_nt); | 7361 | qla4xxx_free_ddb_list(&list_nt); |
6935 | 7362 | ||
6936 | qla4xxx_free_ddb_index(ha); | 7363 | qla4xxx_free_ddb_index(ha); |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index eaa808e6ba91..fe0bcb18fb26 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -78,11 +78,6 @@ static void scsi_done(struct scsi_cmnd *cmd); | |||
78 | * Definitions and constants. | 78 | * Definitions and constants. |
79 | */ | 79 | */ |
80 | 80 | ||
81 | #define MIN_RESET_DELAY (2*HZ) | ||
82 | |||
83 | /* Do not call reset on error if we just did a reset within 15 sec. */ | ||
84 | #define MIN_RESET_PERIOD (15*HZ) | ||
85 | |||
86 | /* | 81 | /* |
87 | * Note - the initial logging level can be set here to log events at boot time. | 82 | * Note - the initial logging level can be set here to log events at boot time. |
88 | * After the system is up, you may enable logging via the /proc interface. | 83 | * After the system is up, you may enable logging via the /proc interface. |
@@ -658,7 +653,6 @@ EXPORT_SYMBOL(scsi_cmd_get_serial); | |||
658 | int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | 653 | int scsi_dispatch_cmd(struct scsi_cmnd *cmd) |
659 | { | 654 | { |
660 | struct Scsi_Host *host = cmd->device->host; | 655 | struct Scsi_Host *host = cmd->device->host; |
661 | unsigned long timeout; | ||
662 | int rtn = 0; | 656 | int rtn = 0; |
663 | 657 | ||
664 | atomic_inc(&cmd->device->iorequest_cnt); | 658 | atomic_inc(&cmd->device->iorequest_cnt); |
@@ -704,28 +698,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | |||
704 | (cmd->device->lun << 5 & 0xe0); | 698 | (cmd->device->lun << 5 & 0xe0); |
705 | } | 699 | } |
706 | 700 | ||
707 | /* | ||
708 | * We will wait MIN_RESET_DELAY clock ticks after the last reset so | ||
709 | * we can avoid the drive not being ready. | ||
710 | */ | ||
711 | timeout = host->last_reset + MIN_RESET_DELAY; | ||
712 | |||
713 | if (host->resetting && time_before(jiffies, timeout)) { | ||
714 | int ticks_remaining = timeout - jiffies; | ||
715 | /* | ||
716 | * NOTE: This may be executed from within an interrupt | ||
717 | * handler! This is bad, but for now, it'll do. The irq | ||
718 | * level of the interrupt handler has been masked out by the | ||
719 | * platform dependent interrupt handling code already, so the | ||
720 | * sti() here will not cause another call to the SCSI host's | ||
721 | * interrupt handler (assuming there is one irq-level per | ||
722 | * host). | ||
723 | */ | ||
724 | while (--ticks_remaining >= 0) | ||
725 | mdelay(1 + 999 / HZ); | ||
726 | host->resetting = 0; | ||
727 | } | ||
728 | |||
729 | scsi_log_send(cmd); | 701 | scsi_log_send(cmd); |
730 | 702 | ||
731 | /* | 703 | /* |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 01c0ffa31276..80b8b10edf41 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -169,7 +169,7 @@ static int scsi_debug_dix = DEF_DIX; | |||
169 | static int scsi_debug_dsense = DEF_D_SENSE; | 169 | static int scsi_debug_dsense = DEF_D_SENSE; |
170 | static int scsi_debug_every_nth = DEF_EVERY_NTH; | 170 | static int scsi_debug_every_nth = DEF_EVERY_NTH; |
171 | static int scsi_debug_fake_rw = DEF_FAKE_RW; | 171 | static int scsi_debug_fake_rw = DEF_FAKE_RW; |
172 | static int scsi_debug_guard = DEF_GUARD; | 172 | static unsigned int scsi_debug_guard = DEF_GUARD; |
173 | static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; | 173 | static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; |
174 | static int scsi_debug_max_luns = DEF_MAX_LUNS; | 174 | static int scsi_debug_max_luns = DEF_MAX_LUNS; |
175 | static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; | 175 | static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; |
@@ -293,6 +293,20 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, | |||
293 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, | 293 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, |
294 | 0, 0, 0x0, 0x0}; | 294 | 0, 0, 0x0, 0x0}; |
295 | 295 | ||
296 | static void *fake_store(unsigned long long lba) | ||
297 | { | ||
298 | lba = do_div(lba, sdebug_store_sectors); | ||
299 | |||
300 | return fake_storep + lba * scsi_debug_sector_size; | ||
301 | } | ||
302 | |||
303 | static struct sd_dif_tuple *dif_store(sector_t sector) | ||
304 | { | ||
305 | sector = do_div(sector, sdebug_store_sectors); | ||
306 | |||
307 | return dif_storep + sector; | ||
308 | } | ||
309 | |||
296 | static int sdebug_add_adapter(void); | 310 | static int sdebug_add_adapter(void); |
297 | static void sdebug_remove_adapter(void); | 311 | static void sdebug_remove_adapter(void); |
298 | 312 | ||
@@ -1731,25 +1745,22 @@ static int do_device_access(struct scsi_cmnd *scmd, | |||
1731 | return ret; | 1745 | return ret; |
1732 | } | 1746 | } |
1733 | 1747 | ||
1734 | static u16 dif_compute_csum(const void *buf, int len) | 1748 | static __be16 dif_compute_csum(const void *buf, int len) |
1735 | { | 1749 | { |
1736 | u16 csum; | 1750 | __be16 csum; |
1737 | 1751 | ||
1738 | switch (scsi_debug_guard) { | 1752 | if (scsi_debug_guard) |
1739 | case 1: | 1753 | csum = (__force __be16)ip_compute_csum(buf, len); |
1740 | csum = ip_compute_csum(buf, len); | 1754 | else |
1741 | break; | ||
1742 | case 0: | ||
1743 | csum = cpu_to_be16(crc_t10dif(buf, len)); | 1755 | csum = cpu_to_be16(crc_t10dif(buf, len)); |
1744 | break; | 1756 | |
1745 | } | ||
1746 | return csum; | 1757 | return csum; |
1747 | } | 1758 | } |
1748 | 1759 | ||
1749 | static int dif_verify(struct sd_dif_tuple *sdt, const void *data, | 1760 | static int dif_verify(struct sd_dif_tuple *sdt, const void *data, |
1750 | sector_t sector, u32 ei_lba) | 1761 | sector_t sector, u32 ei_lba) |
1751 | { | 1762 | { |
1752 | u16 csum = dif_compute_csum(data, scsi_debug_sector_size); | 1763 | __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); |
1753 | 1764 | ||
1754 | if (sdt->guard_tag != csum) { | 1765 | if (sdt->guard_tag != csum) { |
1755 | pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", | 1766 | pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", |
@@ -1775,59 +1786,71 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, | |||
1775 | return 0; | 1786 | return 0; |
1776 | } | 1787 | } |
1777 | 1788 | ||
1778 | static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, | 1789 | static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector, |
1779 | unsigned int sectors, u32 ei_lba) | 1790 | unsigned int sectors, bool read) |
1780 | { | 1791 | { |
1781 | unsigned int i, resid; | 1792 | unsigned int i, resid; |
1782 | struct scatterlist *psgl; | 1793 | struct scatterlist *psgl; |
1783 | struct sd_dif_tuple *sdt; | ||
1784 | sector_t sector; | ||
1785 | sector_t tmp_sec = start_sec; | ||
1786 | void *paddr; | 1794 | void *paddr; |
1795 | const void *dif_store_end = dif_storep + sdebug_store_sectors; | ||
1787 | 1796 | ||
1788 | start_sec = do_div(tmp_sec, sdebug_store_sectors); | 1797 | /* Bytes of protection data to copy into sgl */ |
1798 | resid = sectors * sizeof(*dif_storep); | ||
1789 | 1799 | ||
1790 | sdt = dif_storep + start_sec; | 1800 | scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { |
1801 | int len = min(psgl->length, resid); | ||
1802 | void *start = dif_store(sector); | ||
1803 | int rest = 0; | ||
1791 | 1804 | ||
1792 | for (i = 0 ; i < sectors ; i++) { | 1805 | if (dif_store_end < start + len) |
1793 | int ret; | 1806 | rest = start + len - dif_store_end; |
1794 | 1807 | ||
1795 | if (sdt[i].app_tag == 0xffff) | 1808 | paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; |
1796 | continue; | ||
1797 | 1809 | ||
1798 | sector = start_sec + i; | 1810 | if (read) |
1811 | memcpy(paddr, start, len - rest); | ||
1812 | else | ||
1813 | memcpy(start, paddr, len - rest); | ||
1799 | 1814 | ||
1800 | ret = dif_verify(&sdt[i], | 1815 | if (rest) { |
1801 | fake_storep + sector * scsi_debug_sector_size, | 1816 | if (read) |
1802 | sector, ei_lba); | 1817 | memcpy(paddr + len - rest, dif_storep, rest); |
1803 | if (ret) { | 1818 | else |
1804 | dif_errors++; | 1819 | memcpy(dif_storep, paddr + len - rest, rest); |
1805 | return ret; | ||
1806 | } | 1820 | } |
1807 | 1821 | ||
1808 | ei_lba++; | 1822 | sector += len / sizeof(*dif_storep); |
1823 | resid -= len; | ||
1824 | kunmap_atomic(paddr); | ||
1809 | } | 1825 | } |
1826 | } | ||
1810 | 1827 | ||
1811 | /* Bytes of protection data to copy into sgl */ | 1828 | static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, |
1812 | resid = sectors * sizeof(*dif_storep); | 1829 | unsigned int sectors, u32 ei_lba) |
1813 | sector = start_sec; | 1830 | { |
1831 | unsigned int i; | ||
1832 | struct sd_dif_tuple *sdt; | ||
1833 | sector_t sector; | ||
1814 | 1834 | ||
1815 | scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { | 1835 | for (i = 0; i < sectors; i++) { |
1816 | int len = min(psgl->length, resid); | 1836 | int ret; |
1817 | 1837 | ||
1818 | paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; | 1838 | sector = start_sec + i; |
1819 | memcpy(paddr, dif_storep + sector, len); | 1839 | sdt = dif_store(sector); |
1820 | 1840 | ||
1821 | sector += len / sizeof(*dif_storep); | 1841 | if (sdt->app_tag == cpu_to_be16(0xffff)) |
1822 | if (sector >= sdebug_store_sectors) { | 1842 | continue; |
1823 | /* Force wrap */ | 1843 | |
1824 | tmp_sec = sector; | 1844 | ret = dif_verify(sdt, fake_store(sector), sector, ei_lba); |
1825 | sector = do_div(tmp_sec, sdebug_store_sectors); | 1845 | if (ret) { |
1846 | dif_errors++; | ||
1847 | return ret; | ||
1826 | } | 1848 | } |
1827 | resid -= len; | 1849 | |
1828 | kunmap_atomic(paddr); | 1850 | ei_lba++; |
1829 | } | 1851 | } |
1830 | 1852 | ||
1853 | dif_copy_prot(SCpnt, start_sec, sectors, true); | ||
1831 | dix_reads++; | 1854 | dix_reads++; |
1832 | 1855 | ||
1833 | return 0; | 1856 | return 0; |
@@ -1910,15 +1933,12 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1910 | { | 1933 | { |
1911 | int i, j, ret; | 1934 | int i, j, ret; |
1912 | struct sd_dif_tuple *sdt; | 1935 | struct sd_dif_tuple *sdt; |
1913 | struct scatterlist *dsgl = scsi_sglist(SCpnt); | 1936 | struct scatterlist *dsgl; |
1914 | struct scatterlist *psgl = scsi_prot_sglist(SCpnt); | 1937 | struct scatterlist *psgl = scsi_prot_sglist(SCpnt); |
1915 | void *daddr, *paddr; | 1938 | void *daddr, *paddr; |
1916 | sector_t tmp_sec = start_sec; | 1939 | sector_t sector = start_sec; |
1917 | sector_t sector; | ||
1918 | int ppage_offset; | 1940 | int ppage_offset; |
1919 | 1941 | ||
1920 | sector = do_div(tmp_sec, sdebug_store_sectors); | ||
1921 | |||
1922 | BUG_ON(scsi_sg_count(SCpnt) == 0); | 1942 | BUG_ON(scsi_sg_count(SCpnt) == 0); |
1923 | BUG_ON(scsi_prot_sg_count(SCpnt) == 0); | 1943 | BUG_ON(scsi_prot_sg_count(SCpnt) == 0); |
1924 | 1944 | ||
@@ -1946,25 +1966,13 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1946 | 1966 | ||
1947 | sdt = paddr + ppage_offset; | 1967 | sdt = paddr + ppage_offset; |
1948 | 1968 | ||
1949 | ret = dif_verify(sdt, daddr + j, start_sec, ei_lba); | 1969 | ret = dif_verify(sdt, daddr + j, sector, ei_lba); |
1950 | if (ret) { | 1970 | if (ret) { |
1951 | dump_sector(daddr + j, scsi_debug_sector_size); | 1971 | dump_sector(daddr + j, scsi_debug_sector_size); |
1952 | goto out; | 1972 | goto out; |
1953 | } | 1973 | } |
1954 | 1974 | ||
1955 | /* Would be great to copy this in bigger | ||
1956 | * chunks. However, for the sake of | ||
1957 | * correctness we need to verify each sector | ||
1958 | * before writing it to "stable" storage | ||
1959 | */ | ||
1960 | memcpy(dif_storep + sector, sdt, sizeof(*sdt)); | ||
1961 | |||
1962 | sector++; | 1975 | sector++; |
1963 | |||
1964 | if (sector == sdebug_store_sectors) | ||
1965 | sector = 0; /* Force wrap */ | ||
1966 | |||
1967 | start_sec++; | ||
1968 | ei_lba++; | 1976 | ei_lba++; |
1969 | ppage_offset += sizeof(struct sd_dif_tuple); | 1977 | ppage_offset += sizeof(struct sd_dif_tuple); |
1970 | } | 1978 | } |
@@ -1973,6 +1981,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1973 | kunmap_atomic(daddr); | 1981 | kunmap_atomic(daddr); |
1974 | } | 1982 | } |
1975 | 1983 | ||
1984 | dif_copy_prot(SCpnt, start_sec, sectors, false); | ||
1976 | dix_writes++; | 1985 | dix_writes++; |
1977 | 1986 | ||
1978 | return 0; | 1987 | return 0; |
@@ -2742,7 +2751,7 @@ module_param_named(dix, scsi_debug_dix, int, S_IRUGO); | |||
2742 | module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); | 2751 | module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); |
2743 | module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); | 2752 | module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); |
2744 | module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); | 2753 | module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); |
2745 | module_param_named(guard, scsi_debug_guard, int, S_IRUGO); | 2754 | module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); |
2746 | module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); | 2755 | module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); |
2747 | module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); | 2756 | module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); |
2748 | module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); | 2757 | module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); |
@@ -3172,7 +3181,7 @@ DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL); | |||
3172 | 3181 | ||
3173 | static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) | 3182 | static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf) |
3174 | { | 3183 | { |
3175 | return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard); | 3184 | return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_guard); |
3176 | } | 3185 | } |
3177 | DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); | 3186 | DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL); |
3178 | 3187 | ||
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 83e591b60193..e8bee9f0ad0f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -87,6 +87,18 @@ void scsi_schedule_eh(struct Scsi_Host *shost) | |||
87 | } | 87 | } |
88 | EXPORT_SYMBOL_GPL(scsi_schedule_eh); | 88 | EXPORT_SYMBOL_GPL(scsi_schedule_eh); |
89 | 89 | ||
90 | static int scsi_host_eh_past_deadline(struct Scsi_Host *shost) | ||
91 | { | ||
92 | if (!shost->last_reset || !shost->eh_deadline) | ||
93 | return 0; | ||
94 | |||
95 | if (time_before(jiffies, | ||
96 | shost->last_reset + shost->eh_deadline)) | ||
97 | return 0; | ||
98 | |||
99 | return 1; | ||
100 | } | ||
101 | |||
90 | /** | 102 | /** |
91 | * scsi_eh_scmd_add - add scsi cmd to error handling. | 103 | * scsi_eh_scmd_add - add scsi cmd to error handling. |
92 | * @scmd: scmd to run eh on. | 104 | * @scmd: scmd to run eh on. |
@@ -109,6 +121,9 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
109 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) | 121 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) |
110 | goto out_unlock; | 122 | goto out_unlock; |
111 | 123 | ||
124 | if (shost->eh_deadline && !shost->last_reset) | ||
125 | shost->last_reset = jiffies; | ||
126 | |||
112 | ret = 1; | 127 | ret = 1; |
113 | scmd->eh_eflags |= eh_flag; | 128 | scmd->eh_eflags |= eh_flag; |
114 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 129 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
@@ -138,6 +153,9 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) | |||
138 | trace_scsi_dispatch_cmd_timeout(scmd); | 153 | trace_scsi_dispatch_cmd_timeout(scmd); |
139 | scsi_log_completion(scmd, TIMEOUT_ERROR); | 154 | scsi_log_completion(scmd, TIMEOUT_ERROR); |
140 | 155 | ||
156 | if (host->eh_deadline && !host->last_reset) | ||
157 | host->last_reset = jiffies; | ||
158 | |||
141 | if (host->transportt->eh_timed_out) | 159 | if (host->transportt->eh_timed_out) |
142 | rtn = host->transportt->eh_timed_out(scmd); | 160 | rtn = host->transportt->eh_timed_out(scmd); |
143 | else if (host->hostt->eh_timed_out) | 161 | else if (host->hostt->eh_timed_out) |
@@ -990,13 +1008,26 @@ int scsi_eh_get_sense(struct list_head *work_q, | |||
990 | struct list_head *done_q) | 1008 | struct list_head *done_q) |
991 | { | 1009 | { |
992 | struct scsi_cmnd *scmd, *next; | 1010 | struct scsi_cmnd *scmd, *next; |
1011 | struct Scsi_Host *shost; | ||
993 | int rtn; | 1012 | int rtn; |
1013 | unsigned long flags; | ||
994 | 1014 | ||
995 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1015 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
996 | if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || | 1016 | if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || |
997 | SCSI_SENSE_VALID(scmd)) | 1017 | SCSI_SENSE_VALID(scmd)) |
998 | continue; | 1018 | continue; |
999 | 1019 | ||
1020 | shost = scmd->device->host; | ||
1021 | spin_lock_irqsave(shost->host_lock, flags); | ||
1022 | if (scsi_host_eh_past_deadline(shost)) { | ||
1023 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1024 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1025 | shost_printk(KERN_INFO, shost, | ||
1026 | "skip %s, past eh deadline\n", | ||
1027 | __func__)); | ||
1028 | break; | ||
1029 | } | ||
1030 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1000 | SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, | 1031 | SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, |
1001 | "%s: requesting sense\n", | 1032 | "%s: requesting sense\n", |
1002 | current->comm)); | 1033 | current->comm)); |
@@ -1082,11 +1113,28 @@ static int scsi_eh_test_devices(struct list_head *cmd_list, | |||
1082 | struct scsi_cmnd *scmd, *next; | 1113 | struct scsi_cmnd *scmd, *next; |
1083 | struct scsi_device *sdev; | 1114 | struct scsi_device *sdev; |
1084 | int finish_cmds; | 1115 | int finish_cmds; |
1116 | unsigned long flags; | ||
1085 | 1117 | ||
1086 | while (!list_empty(cmd_list)) { | 1118 | while (!list_empty(cmd_list)) { |
1087 | scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); | 1119 | scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); |
1088 | sdev = scmd->device; | 1120 | sdev = scmd->device; |
1089 | 1121 | ||
1122 | if (!try_stu) { | ||
1123 | spin_lock_irqsave(sdev->host->host_lock, flags); | ||
1124 | if (scsi_host_eh_past_deadline(sdev->host)) { | ||
1125 | /* Push items back onto work_q */ | ||
1126 | list_splice_init(cmd_list, work_q); | ||
1127 | spin_unlock_irqrestore(sdev->host->host_lock, | ||
1128 | flags); | ||
1129 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1130 | shost_printk(KERN_INFO, sdev->host, | ||
1131 | "skip %s, past eh deadline", | ||
1132 | __func__)); | ||
1133 | break; | ||
1134 | } | ||
1135 | spin_unlock_irqrestore(sdev->host->host_lock, flags); | ||
1136 | } | ||
1137 | |||
1090 | finish_cmds = !scsi_device_online(scmd->device) || | 1138 | finish_cmds = !scsi_device_online(scmd->device) || |
1091 | (try_stu && !scsi_eh_try_stu(scmd) && | 1139 | (try_stu && !scsi_eh_try_stu(scmd) && |
1092 | !scsi_eh_tur(scmd)) || | 1140 | !scsi_eh_tur(scmd)) || |
@@ -1122,26 +1170,42 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
1122 | struct scsi_cmnd *scmd, *next; | 1170 | struct scsi_cmnd *scmd, *next; |
1123 | LIST_HEAD(check_list); | 1171 | LIST_HEAD(check_list); |
1124 | int rtn; | 1172 | int rtn; |
1173 | struct Scsi_Host *shost; | ||
1174 | unsigned long flags; | ||
1125 | 1175 | ||
1126 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1176 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
1127 | if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD)) | 1177 | if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD)) |
1128 | continue; | 1178 | continue; |
1179 | shost = scmd->device->host; | ||
1180 | spin_lock_irqsave(shost->host_lock, flags); | ||
1181 | if (scsi_host_eh_past_deadline(shost)) { | ||
1182 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1183 | list_splice_init(&check_list, work_q); | ||
1184 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1185 | shost_printk(KERN_INFO, shost, | ||
1186 | "skip %s, past eh deadline\n", | ||
1187 | __func__)); | ||
1188 | return list_empty(work_q); | ||
1189 | } | ||
1190 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1129 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" | 1191 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" |
1130 | "0x%p\n", current->comm, | 1192 | "0x%p\n", current->comm, |
1131 | scmd)); | 1193 | scmd)); |
1132 | rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); | 1194 | rtn = scsi_try_to_abort_cmd(shost->hostt, scmd); |
1133 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1195 | if (rtn == FAILED) { |
1134 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; | ||
1135 | if (rtn == FAST_IO_FAIL) | ||
1136 | scsi_eh_finish_cmd(scmd, done_q); | ||
1137 | else | ||
1138 | list_move_tail(&scmd->eh_entry, &check_list); | ||
1139 | } else | ||
1140 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" | 1196 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" |
1141 | " cmd failed:" | 1197 | " cmd failed:" |
1142 | "0x%p\n", | 1198 | "0x%p\n", |
1143 | current->comm, | 1199 | current->comm, |
1144 | scmd)); | 1200 | scmd)); |
1201 | list_splice_init(&check_list, work_q); | ||
1202 | return list_empty(work_q); | ||
1203 | } | ||
1204 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; | ||
1205 | if (rtn == FAST_IO_FAIL) | ||
1206 | scsi_eh_finish_cmd(scmd, done_q); | ||
1207 | else | ||
1208 | list_move_tail(&scmd->eh_entry, &check_list); | ||
1145 | } | 1209 | } |
1146 | 1210 | ||
1147 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); | 1211 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
@@ -1187,8 +1251,19 @@ static int scsi_eh_stu(struct Scsi_Host *shost, | |||
1187 | { | 1251 | { |
1188 | struct scsi_cmnd *scmd, *stu_scmd, *next; | 1252 | struct scsi_cmnd *scmd, *stu_scmd, *next; |
1189 | struct scsi_device *sdev; | 1253 | struct scsi_device *sdev; |
1254 | unsigned long flags; | ||
1190 | 1255 | ||
1191 | shost_for_each_device(sdev, shost) { | 1256 | shost_for_each_device(sdev, shost) { |
1257 | spin_lock_irqsave(shost->host_lock, flags); | ||
1258 | if (scsi_host_eh_past_deadline(shost)) { | ||
1259 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1260 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1261 | shost_printk(KERN_INFO, shost, | ||
1262 | "skip %s, past eh deadline\n", | ||
1263 | __func__)); | ||
1264 | break; | ||
1265 | } | ||
1266 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1192 | stu_scmd = NULL; | 1267 | stu_scmd = NULL; |
1193 | list_for_each_entry(scmd, work_q, eh_entry) | 1268 | list_for_each_entry(scmd, work_q, eh_entry) |
1194 | if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && | 1269 | if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && |
@@ -1241,9 +1316,20 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, | |||
1241 | { | 1316 | { |
1242 | struct scsi_cmnd *scmd, *bdr_scmd, *next; | 1317 | struct scsi_cmnd *scmd, *bdr_scmd, *next; |
1243 | struct scsi_device *sdev; | 1318 | struct scsi_device *sdev; |
1319 | unsigned long flags; | ||
1244 | int rtn; | 1320 | int rtn; |
1245 | 1321 | ||
1246 | shost_for_each_device(sdev, shost) { | 1322 | shost_for_each_device(sdev, shost) { |
1323 | spin_lock_irqsave(shost->host_lock, flags); | ||
1324 | if (scsi_host_eh_past_deadline(shost)) { | ||
1325 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1326 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1327 | shost_printk(KERN_INFO, shost, | ||
1328 | "skip %s, past eh deadline\n", | ||
1329 | __func__)); | ||
1330 | break; | ||
1331 | } | ||
1332 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1247 | bdr_scmd = NULL; | 1333 | bdr_scmd = NULL; |
1248 | list_for_each_entry(scmd, work_q, eh_entry) | 1334 | list_for_each_entry(scmd, work_q, eh_entry) |
1249 | if (scmd->device == sdev) { | 1335 | if (scmd->device == sdev) { |
@@ -1303,6 +1389,21 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
1303 | struct scsi_cmnd *next, *scmd; | 1389 | struct scsi_cmnd *next, *scmd; |
1304 | int rtn; | 1390 | int rtn; |
1305 | unsigned int id; | 1391 | unsigned int id; |
1392 | unsigned long flags; | ||
1393 | |||
1394 | spin_lock_irqsave(shost->host_lock, flags); | ||
1395 | if (scsi_host_eh_past_deadline(shost)) { | ||
1396 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1397 | /* push back on work queue for further processing */ | ||
1398 | list_splice_init(&check_list, work_q); | ||
1399 | list_splice_init(&tmp_list, work_q); | ||
1400 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1401 | shost_printk(KERN_INFO, shost, | ||
1402 | "skip %s, past eh deadline\n", | ||
1403 | __func__)); | ||
1404 | return list_empty(work_q); | ||
1405 | } | ||
1406 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1306 | 1407 | ||
1307 | scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); | 1408 | scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); |
1308 | id = scmd_id(scmd); | 1409 | id = scmd_id(scmd); |
@@ -1347,6 +1448,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
1347 | LIST_HEAD(check_list); | 1448 | LIST_HEAD(check_list); |
1348 | unsigned int channel; | 1449 | unsigned int channel; |
1349 | int rtn; | 1450 | int rtn; |
1451 | unsigned long flags; | ||
1350 | 1452 | ||
1351 | /* | 1453 | /* |
1352 | * we really want to loop over the various channels, and do this on | 1454 | * we really want to loop over the various channels, and do this on |
@@ -1356,6 +1458,18 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
1356 | */ | 1458 | */ |
1357 | 1459 | ||
1358 | for (channel = 0; channel <= shost->max_channel; channel++) { | 1460 | for (channel = 0; channel <= shost->max_channel; channel++) { |
1461 | spin_lock_irqsave(shost->host_lock, flags); | ||
1462 | if (scsi_host_eh_past_deadline(shost)) { | ||
1463 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1464 | list_splice_init(&check_list, work_q); | ||
1465 | SCSI_LOG_ERROR_RECOVERY(3, | ||
1466 | shost_printk(KERN_INFO, shost, | ||
1467 | "skip %s, past eh deadline\n", | ||
1468 | __func__)); | ||
1469 | return list_empty(work_q); | ||
1470 | } | ||
1471 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1472 | |||
1359 | chan_scmd = NULL; | 1473 | chan_scmd = NULL; |
1360 | list_for_each_entry(scmd, work_q, eh_entry) { | 1474 | list_for_each_entry(scmd, work_q, eh_entry) { |
1361 | if (channel == scmd_channel(scmd)) { | 1475 | if (channel == scmd_channel(scmd)) { |
@@ -1755,8 +1869,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1755 | * will be requests for character device operations, and also for | 1869 | * will be requests for character device operations, and also for |
1756 | * ioctls to queued block devices. | 1870 | * ioctls to queued block devices. |
1757 | */ | 1871 | */ |
1758 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1872 | SCSI_LOG_ERROR_RECOVERY(3, |
1759 | __func__)); | 1873 | printk("scsi_eh_%d waking up host to restart\n", |
1874 | shost->host_no)); | ||
1760 | 1875 | ||
1761 | spin_lock_irqsave(shost->host_lock, flags); | 1876 | spin_lock_irqsave(shost->host_lock, flags); |
1762 | if (scsi_host_set_state(shost, SHOST_RUNNING)) | 1877 | if (scsi_host_set_state(shost, SHOST_RUNNING)) |
@@ -1883,6 +1998,10 @@ static void scsi_unjam_host(struct Scsi_Host *shost) | |||
1883 | if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q)) | 1998 | if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q)) |
1884 | scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); | 1999 | scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); |
1885 | 2000 | ||
2001 | spin_lock_irqsave(shost->host_lock, flags); | ||
2002 | if (shost->eh_deadline) | ||
2003 | shost->last_reset = 0; | ||
2004 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1886 | scsi_eh_flush_done_q(&eh_done_q); | 2005 | scsi_eh_flush_done_q(&eh_done_q); |
1887 | } | 2006 | } |
1888 | 2007 | ||
@@ -1909,7 +2028,7 @@ int scsi_error_handler(void *data) | |||
1909 | if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || | 2028 | if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || |
1910 | shost->host_failed != shost->host_busy) { | 2029 | shost->host_failed != shost->host_busy) { |
1911 | SCSI_LOG_ERROR_RECOVERY(1, | 2030 | SCSI_LOG_ERROR_RECOVERY(1, |
1912 | printk("Error handler scsi_eh_%d sleeping\n", | 2031 | printk("scsi_eh_%d: sleeping\n", |
1913 | shost->host_no)); | 2032 | shost->host_no)); |
1914 | schedule(); | 2033 | schedule(); |
1915 | continue; | 2034 | continue; |
@@ -1917,8 +2036,9 @@ int scsi_error_handler(void *data) | |||
1917 | 2036 | ||
1918 | __set_current_state(TASK_RUNNING); | 2037 | __set_current_state(TASK_RUNNING); |
1919 | SCSI_LOG_ERROR_RECOVERY(1, | 2038 | SCSI_LOG_ERROR_RECOVERY(1, |
1920 | printk("Error handler scsi_eh_%d waking up\n", | 2039 | printk("scsi_eh_%d: waking up %d/%d/%d\n", |
1921 | shost->host_no)); | 2040 | shost->host_no, shost->host_eh_scheduled, |
2041 | shost->host_failed, shost->host_busy)); | ||
1922 | 2042 | ||
1923 | /* | 2043 | /* |
1924 | * We have a host that is failing for some reason. Figure out | 2044 | * We have a host that is failing for some reason. Figure out |
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 4c5aabe21755..af4c050ce6e4 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c | |||
@@ -54,7 +54,8 @@ scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *)) | |||
54 | /* | 54 | /* |
55 | * All the high-level SCSI drivers that implement runtime | 55 | * All the high-level SCSI drivers that implement runtime |
56 | * PM treat runtime suspend, system suspend, and system | 56 | * PM treat runtime suspend, system suspend, and system |
57 | * hibernate identically. | 57 | * hibernate nearly identically. In all cases the requirements |
58 | * for runtime suspension are stricter. | ||
58 | */ | 59 | */ |
59 | if (pm_runtime_suspended(dev)) | 60 | if (pm_runtime_suspended(dev)) |
60 | return 0; | 61 | return 0; |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 40c639491b27..8ff62c26a41c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -281,6 +281,42 @@ exit_store_host_reset: | |||
281 | 281 | ||
282 | static DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset); | 282 | static DEVICE_ATTR(host_reset, S_IWUSR, NULL, store_host_reset); |
283 | 283 | ||
284 | static ssize_t | ||
285 | show_shost_eh_deadline(struct device *dev, | ||
286 | struct device_attribute *attr, char *buf) | ||
287 | { | ||
288 | struct Scsi_Host *shost = class_to_shost(dev); | ||
289 | |||
290 | return sprintf(buf, "%d\n", shost->eh_deadline / HZ); | ||
291 | } | ||
292 | |||
293 | static ssize_t | ||
294 | store_shost_eh_deadline(struct device *dev, struct device_attribute *attr, | ||
295 | const char *buf, size_t count) | ||
296 | { | ||
297 | struct Scsi_Host *shost = class_to_shost(dev); | ||
298 | int ret = -EINVAL; | ||
299 | int deadline; | ||
300 | unsigned long flags; | ||
301 | |||
302 | if (shost->transportt && shost->transportt->eh_strategy_handler) | ||
303 | return ret; | ||
304 | |||
305 | if (sscanf(buf, "%d\n", &deadline) == 1) { | ||
306 | spin_lock_irqsave(shost->host_lock, flags); | ||
307 | if (scsi_host_in_recovery(shost)) | ||
308 | ret = -EBUSY; | ||
309 | else { | ||
310 | shost->eh_deadline = deadline * HZ; | ||
311 | ret = count; | ||
312 | } | ||
313 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
314 | } | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); | ||
319 | |||
284 | shost_rd_attr(unique_id, "%u\n"); | 320 | shost_rd_attr(unique_id, "%u\n"); |
285 | shost_rd_attr(host_busy, "%hu\n"); | 321 | shost_rd_attr(host_busy, "%hu\n"); |
286 | shost_rd_attr(cmd_per_lun, "%hd\n"); | 322 | shost_rd_attr(cmd_per_lun, "%hd\n"); |
@@ -308,6 +344,7 @@ static struct attribute *scsi_sysfs_shost_attrs[] = { | |||
308 | &dev_attr_prot_capabilities.attr, | 344 | &dev_attr_prot_capabilities.attr, |
309 | &dev_attr_prot_guard_type.attr, | 345 | &dev_attr_prot_guard_type.attr, |
310 | &dev_attr_host_reset.attr, | 346 | &dev_attr_host_reset.attr, |
347 | &dev_attr_eh_deadline.attr, | ||
311 | NULL | 348 | NULL |
312 | }; | 349 | }; |
313 | 350 | ||
@@ -529,6 +566,7 @@ static int scsi_sdev_check_buf_bit(const char *buf) | |||
529 | */ | 566 | */ |
530 | sdev_rd_attr (device_blocked, "%d\n"); | 567 | sdev_rd_attr (device_blocked, "%d\n"); |
531 | sdev_rd_attr (queue_depth, "%d\n"); | 568 | sdev_rd_attr (queue_depth, "%d\n"); |
569 | sdev_rd_attr (device_busy, "%d\n"); | ||
532 | sdev_rd_attr (type, "%d\n"); | 570 | sdev_rd_attr (type, "%d\n"); |
533 | sdev_rd_attr (scsi_level, "%d\n"); | 571 | sdev_rd_attr (scsi_level, "%d\n"); |
534 | sdev_rd_attr (vendor, "%.8s\n"); | 572 | sdev_rd_attr (vendor, "%.8s\n"); |
@@ -750,6 +788,7 @@ static struct attribute *scsi_sdev_attrs[] = { | |||
750 | &dev_attr_device_blocked.attr, | 788 | &dev_attr_device_blocked.attr, |
751 | &dev_attr_type.attr, | 789 | &dev_attr_type.attr, |
752 | &dev_attr_scsi_level.attr, | 790 | &dev_attr_scsi_level.attr, |
791 | &dev_attr_device_busy.attr, | ||
753 | &dev_attr_vendor.attr, | 792 | &dev_attr_vendor.attr, |
754 | &dev_attr_model.attr, | 793 | &dev_attr_model.attr, |
755 | &dev_attr_rev.attr, | 794 | &dev_attr_rev.attr, |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e4a989fa477d..63a6ca49d4e5 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -2744,6 +2744,28 @@ exit_get_chap: | |||
2744 | return err; | 2744 | return err; |
2745 | } | 2745 | } |
2746 | 2746 | ||
2747 | static int iscsi_set_chap(struct iscsi_transport *transport, | ||
2748 | struct iscsi_uevent *ev, uint32_t len) | ||
2749 | { | ||
2750 | char *data = (char *)ev + sizeof(*ev); | ||
2751 | struct Scsi_Host *shost; | ||
2752 | int err = 0; | ||
2753 | |||
2754 | if (!transport->set_chap) | ||
2755 | return -ENOSYS; | ||
2756 | |||
2757 | shost = scsi_host_lookup(ev->u.set_path.host_no); | ||
2758 | if (!shost) { | ||
2759 | pr_err("%s could not find host no %u\n", | ||
2760 | __func__, ev->u.set_path.host_no); | ||
2761 | return -ENODEV; | ||
2762 | } | ||
2763 | |||
2764 | err = transport->set_chap(shost, data, len); | ||
2765 | scsi_host_put(shost); | ||
2766 | return err; | ||
2767 | } | ||
2768 | |||
2747 | static int iscsi_delete_chap(struct iscsi_transport *transport, | 2769 | static int iscsi_delete_chap(struct iscsi_transport *transport, |
2748 | struct iscsi_uevent *ev) | 2770 | struct iscsi_uevent *ev) |
2749 | { | 2771 | { |
@@ -3234,6 +3256,10 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) | |||
3234 | case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID: | 3256 | case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID: |
3235 | err = iscsi_logout_flashnode_sid(transport, ev); | 3257 | err = iscsi_logout_flashnode_sid(transport, ev); |
3236 | break; | 3258 | break; |
3259 | case ISCSI_UEVENT_SET_CHAP: | ||
3260 | err = iscsi_set_chap(transport, ev, | ||
3261 | nlmsg_attrlen(nlh, sizeof(*ev))); | ||
3262 | break; | ||
3237 | default: | 3263 | default: |
3238 | err = -ENOSYS; | 3264 | err = -ENOSYS; |
3239 | break; | 3265 | break; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7fe4faaa149b..e6c4bff04339 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -105,7 +105,8 @@ static void sd_unlock_native_capacity(struct gendisk *disk); | |||
105 | static int sd_probe(struct device *); | 105 | static int sd_probe(struct device *); |
106 | static int sd_remove(struct device *); | 106 | static int sd_remove(struct device *); |
107 | static void sd_shutdown(struct device *); | 107 | static void sd_shutdown(struct device *); |
108 | static int sd_suspend(struct device *); | 108 | static int sd_suspend_system(struct device *); |
109 | static int sd_suspend_runtime(struct device *); | ||
109 | static int sd_resume(struct device *); | 110 | static int sd_resume(struct device *); |
110 | static void sd_rescan(struct device *); | 111 | static void sd_rescan(struct device *); |
111 | static int sd_done(struct scsi_cmnd *); | 112 | static int sd_done(struct scsi_cmnd *); |
@@ -484,11 +485,11 @@ static struct class sd_disk_class = { | |||
484 | }; | 485 | }; |
485 | 486 | ||
486 | static const struct dev_pm_ops sd_pm_ops = { | 487 | static const struct dev_pm_ops sd_pm_ops = { |
487 | .suspend = sd_suspend, | 488 | .suspend = sd_suspend_system, |
488 | .resume = sd_resume, | 489 | .resume = sd_resume, |
489 | .poweroff = sd_suspend, | 490 | .poweroff = sd_suspend_system, |
490 | .restore = sd_resume, | 491 | .restore = sd_resume, |
491 | .runtime_suspend = sd_suspend, | 492 | .runtime_suspend = sd_suspend_runtime, |
492 | .runtime_resume = sd_resume, | 493 | .runtime_resume = sd_resume, |
493 | }; | 494 | }; |
494 | 495 | ||
@@ -829,7 +830,7 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) | |||
829 | 830 | ||
830 | static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) | 831 | static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) |
831 | { | 832 | { |
832 | rq->timeout = SD_FLUSH_TIMEOUT; | 833 | rq->timeout *= SD_FLUSH_TIMEOUT_MULTIPLIER; |
833 | rq->retries = SD_MAX_RETRIES; | 834 | rq->retries = SD_MAX_RETRIES; |
834 | rq->cmd[0] = SYNCHRONIZE_CACHE; | 835 | rq->cmd[0] = SYNCHRONIZE_CACHE; |
835 | rq->cmd_len = 10; | 836 | rq->cmd_len = 10; |
@@ -1433,12 +1434,13 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1433 | { | 1434 | { |
1434 | int retries, res; | 1435 | int retries, res; |
1435 | struct scsi_device *sdp = sdkp->device; | 1436 | struct scsi_device *sdp = sdkp->device; |
1437 | const int timeout = sdp->request_queue->rq_timeout | ||
1438 | * SD_FLUSH_TIMEOUT_MULTIPLIER; | ||
1436 | struct scsi_sense_hdr sshdr; | 1439 | struct scsi_sense_hdr sshdr; |
1437 | 1440 | ||
1438 | if (!scsi_device_online(sdp)) | 1441 | if (!scsi_device_online(sdp)) |
1439 | return -ENODEV; | 1442 | return -ENODEV; |
1440 | 1443 | ||
1441 | |||
1442 | for (retries = 3; retries > 0; --retries) { | 1444 | for (retries = 3; retries > 0; --retries) { |
1443 | unsigned char cmd[10] = { 0 }; | 1445 | unsigned char cmd[10] = { 0 }; |
1444 | 1446 | ||
@@ -1448,20 +1450,39 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1448 | * flush everything. | 1450 | * flush everything. |
1449 | */ | 1451 | */ |
1450 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, | 1452 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, |
1451 | &sshdr, SD_FLUSH_TIMEOUT, | 1453 | &sshdr, timeout, SD_MAX_RETRIES, |
1452 | SD_MAX_RETRIES, NULL, REQ_PM); | 1454 | NULL, REQ_PM); |
1453 | if (res == 0) | 1455 | if (res == 0) |
1454 | break; | 1456 | break; |
1455 | } | 1457 | } |
1456 | 1458 | ||
1457 | if (res) { | 1459 | if (res) { |
1458 | sd_print_result(sdkp, res); | 1460 | sd_print_result(sdkp, res); |
1461 | |||
1459 | if (driver_byte(res) & DRIVER_SENSE) | 1462 | if (driver_byte(res) & DRIVER_SENSE) |
1460 | sd_print_sense_hdr(sdkp, &sshdr); | 1463 | sd_print_sense_hdr(sdkp, &sshdr); |
1464 | /* we need to evaluate the error return */ | ||
1465 | if (scsi_sense_valid(&sshdr) && | ||
1466 | /* 0x3a is medium not present */ | ||
1467 | sshdr.asc == 0x3a) | ||
1468 | /* this is no error here */ | ||
1469 | return 0; | ||
1470 | |||
1471 | switch (host_byte(res)) { | ||
1472 | /* ignore errors due to racing a disconnection */ | ||
1473 | case DID_BAD_TARGET: | ||
1474 | case DID_NO_CONNECT: | ||
1475 | return 0; | ||
1476 | /* signal the upper layer it might try again */ | ||
1477 | case DID_BUS_BUSY: | ||
1478 | case DID_IMM_RETRY: | ||
1479 | case DID_REQUEUE: | ||
1480 | case DID_SOFT_ERROR: | ||
1481 | return -EBUSY; | ||
1482 | default: | ||
1483 | return -EIO; | ||
1484 | } | ||
1461 | } | 1485 | } |
1462 | |||
1463 | if (res) | ||
1464 | return -EIO; | ||
1465 | return 0; | 1486 | return 0; |
1466 | } | 1487 | } |
1467 | 1488 | ||
@@ -2639,13 +2660,16 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) | |||
2639 | struct scsi_device *sdev = sdkp->device; | 2660 | struct scsi_device *sdev = sdkp->device; |
2640 | 2661 | ||
2641 | if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { | 2662 | if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { |
2663 | /* too large values might cause issues with arcmsr */ | ||
2664 | int vpd_buf_len = 64; | ||
2665 | |||
2642 | sdev->no_report_opcodes = 1; | 2666 | sdev->no_report_opcodes = 1; |
2643 | 2667 | ||
2644 | /* Disable WRITE SAME if REPORT SUPPORTED OPERATION | 2668 | /* Disable WRITE SAME if REPORT SUPPORTED OPERATION |
2645 | * CODES is unsupported and the device has an ATA | 2669 | * CODES is unsupported and the device has an ATA |
2646 | * Information VPD page (SAT). | 2670 | * Information VPD page (SAT). |
2647 | */ | 2671 | */ |
2648 | if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE)) | 2672 | if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len)) |
2649 | sdev->no_write_same = 1; | 2673 | sdev->no_write_same = 1; |
2650 | } | 2674 | } |
2651 | 2675 | ||
@@ -3058,9 +3082,17 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) | |||
3058 | sd_print_result(sdkp, res); | 3082 | sd_print_result(sdkp, res); |
3059 | if (driver_byte(res) & DRIVER_SENSE) | 3083 | if (driver_byte(res) & DRIVER_SENSE) |
3060 | sd_print_sense_hdr(sdkp, &sshdr); | 3084 | sd_print_sense_hdr(sdkp, &sshdr); |
3085 | if (scsi_sense_valid(&sshdr) && | ||
3086 | /* 0x3a is medium not present */ | ||
3087 | sshdr.asc == 0x3a) | ||
3088 | res = 0; | ||
3061 | } | 3089 | } |
3062 | 3090 | ||
3063 | return res; | 3091 | /* SCSI error codes must not go to the generic layer */ |
3092 | if (res) | ||
3093 | return -EIO; | ||
3094 | |||
3095 | return 0; | ||
3064 | } | 3096 | } |
3065 | 3097 | ||
3066 | /* | 3098 | /* |
@@ -3078,7 +3110,7 @@ static void sd_shutdown(struct device *dev) | |||
3078 | if (pm_runtime_suspended(dev)) | 3110 | if (pm_runtime_suspended(dev)) |
3079 | goto exit; | 3111 | goto exit; |
3080 | 3112 | ||
3081 | if (sdkp->WCE) { | 3113 | if (sdkp->WCE && sdkp->media_present) { |
3082 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); | 3114 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); |
3083 | sd_sync_cache(sdkp); | 3115 | sd_sync_cache(sdkp); |
3084 | } | 3116 | } |
@@ -3092,7 +3124,7 @@ exit: | |||
3092 | scsi_disk_put(sdkp); | 3124 | scsi_disk_put(sdkp); |
3093 | } | 3125 | } |
3094 | 3126 | ||
3095 | static int sd_suspend(struct device *dev) | 3127 | static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) |
3096 | { | 3128 | { |
3097 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3129 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); |
3098 | int ret = 0; | 3130 | int ret = 0; |
@@ -3100,16 +3132,23 @@ static int sd_suspend(struct device *dev) | |||
3100 | if (!sdkp) | 3132 | if (!sdkp) |
3101 | return 0; /* this can happen */ | 3133 | return 0; /* this can happen */ |
3102 | 3134 | ||
3103 | if (sdkp->WCE) { | 3135 | if (sdkp->WCE && sdkp->media_present) { |
3104 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); | 3136 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); |
3105 | ret = sd_sync_cache(sdkp); | 3137 | ret = sd_sync_cache(sdkp); |
3106 | if (ret) | 3138 | if (ret) { |
3139 | /* ignore OFFLINE device */ | ||
3140 | if (ret == -ENODEV) | ||
3141 | ret = 0; | ||
3107 | goto done; | 3142 | goto done; |
3143 | } | ||
3108 | } | 3144 | } |
3109 | 3145 | ||
3110 | if (sdkp->device->manage_start_stop) { | 3146 | if (sdkp->device->manage_start_stop) { |
3111 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); | 3147 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); |
3148 | /* an error is not worth aborting a system sleep */ | ||
3112 | ret = sd_start_stop_device(sdkp, 0); | 3149 | ret = sd_start_stop_device(sdkp, 0); |
3150 | if (ignore_stop_errors) | ||
3151 | ret = 0; | ||
3113 | } | 3152 | } |
3114 | 3153 | ||
3115 | done: | 3154 | done: |
@@ -3117,6 +3156,16 @@ done: | |||
3117 | return ret; | 3156 | return ret; |
3118 | } | 3157 | } |
3119 | 3158 | ||
3159 | static int sd_suspend_system(struct device *dev) | ||
3160 | { | ||
3161 | return sd_suspend_common(dev, true); | ||
3162 | } | ||
3163 | |||
3164 | static int sd_suspend_runtime(struct device *dev) | ||
3165 | { | ||
3166 | return sd_suspend_common(dev, false); | ||
3167 | } | ||
3168 | |||
3120 | static int sd_resume(struct device *dev) | 3169 | static int sd_resume(struct device *dev) |
3121 | { | 3170 | { |
3122 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3171 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); |
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 7a049de22051..26895ff247c5 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
@@ -13,7 +13,11 @@ | |||
13 | */ | 13 | */ |
14 | #define SD_TIMEOUT (30 * HZ) | 14 | #define SD_TIMEOUT (30 * HZ) |
15 | #define SD_MOD_TIMEOUT (75 * HZ) | 15 | #define SD_MOD_TIMEOUT (75 * HZ) |
16 | #define SD_FLUSH_TIMEOUT (60 * HZ) | 16 | /* |
17 | * Flush timeout is a multiplier over the standard device timeout which is | ||
18 | * user modifiable via sysfs but initially set to SD_TIMEOUT | ||
19 | */ | ||
20 | #define SD_FLUSH_TIMEOUT_MULTIPLIER 2 | ||
17 | #define SD_WRITE_SAME_TIMEOUT (120 * HZ) | 21 | #define SD_WRITE_SAME_TIMEOUT (120 * HZ) |
18 | 22 | ||
19 | /* | 23 | /* |
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 9327f5fcec4e..11423615c2ea 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c | |||
@@ -521,7 +521,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr | |||
521 | pACB->SelConn++; | 521 | pACB->SelConn++; |
522 | return 1; | 522 | return 1; |
523 | } | 523 | } |
524 | if (time_before (jiffies, pACB->pScsiHost->last_reset)) | 524 | if (time_before (jiffies, pACB->last_reset)) |
525 | { | 525 | { |
526 | DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n")); | 526 | DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n")); |
527 | return 1; | 527 | return 1; |
@@ -1863,7 +1863,7 @@ dc390_ScsiRstDetect( struct dc390_acb* pACB ) | |||
1863 | /* delay half a second */ | 1863 | /* delay half a second */ |
1864 | udelay (1000); | 1864 | udelay (1000); |
1865 | DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); | 1865 | DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); |
1866 | pACB->pScsiHost->last_reset = jiffies + 5*HZ/2 | 1866 | pACB->last_reset = jiffies + 5*HZ/2 |
1867 | + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; | 1867 | + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; |
1868 | pACB->Connected = 0; | 1868 | pACB->Connected = 0; |
1869 | 1869 | ||
@@ -2048,9 +2048,9 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd) | |||
2048 | 2048 | ||
2049 | dc390_ResetDevParam(pACB); | 2049 | dc390_ResetDevParam(pACB); |
2050 | mdelay(1); | 2050 | mdelay(1); |
2051 | pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 | 2051 | pACB->last_reset = jiffies + 3*HZ/2 |
2052 | + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; | 2052 | + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; |
2053 | 2053 | ||
2054 | DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); | 2054 | DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); |
2055 | DC390_read8(INT_Status); /* Reset Pending INT */ | 2055 | DC390_read8(INT_Status); /* Reset Pending INT */ |
2056 | 2056 | ||
@@ -2383,7 +2383,7 @@ static void dc390_init_hw(struct dc390_acb *pACB, u8 index) | |||
2383 | if (pACB->Gmode2 & RST_SCSI_BUS) { | 2383 | if (pACB->Gmode2 & RST_SCSI_BUS) { |
2384 | dc390_ResetSCSIBus(pACB); | 2384 | dc390_ResetSCSIBus(pACB); |
2385 | udelay(1000); | 2385 | udelay(1000); |
2386 | shost->last_reset = jiffies + HZ/2 + | 2386 | pACB->last_reset = jiffies + HZ/2 + |
2387 | HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; | 2387 | HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; |
2388 | } | 2388 | } |
2389 | 2389 | ||
@@ -2455,8 +2455,8 @@ static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2455 | shost->irq = pdev->irq; | 2455 | shost->irq = pdev->irq; |
2456 | shost->base = io_port; | 2456 | shost->base = io_port; |
2457 | shost->unique_id = io_port; | 2457 | shost->unique_id = io_port; |
2458 | shost->last_reset = jiffies; | 2458 | |
2459 | 2459 | pACB->last_reset = jiffies; | |
2460 | pACB->pScsiHost = shost; | 2460 | pACB->pScsiHost = shost; |
2461 | pACB->IOPortBase = (u16) io_port; | 2461 | pACB->IOPortBase = (u16) io_port; |
2462 | pACB->IRQLevel = pdev->irq; | 2462 | pACB->IRQLevel = pdev->irq; |
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h index 77adc54dbd16..3d1bb4ad1826 100644 --- a/drivers/scsi/tmscsim.h +++ b/drivers/scsi/tmscsim.h | |||
@@ -143,6 +143,7 @@ u8 Ignore_IRQ; /* Not used */ | |||
143 | 143 | ||
144 | struct pci_dev *pdev; | 144 | struct pci_dev *pdev; |
145 | 145 | ||
146 | unsigned long last_reset; | ||
146 | unsigned long Cmds; | 147 | unsigned long Cmds; |
147 | u32 SelLost; | 148 | u32 SelLost; |
148 | u32 SelConn; | 149 | u32 SelConn; |
diff --git a/include/scsi/fc/fc_fc2.h b/include/scsi/fc/fc_fc2.h index f87777d0d5bd..0b2671431305 100644 --- a/include/scsi/fc/fc_fc2.h +++ b/include/scsi/fc/fc_fc2.h | |||
@@ -104,7 +104,7 @@ struct fc_esb { | |||
104 | * esb_e_stat - flags from FC-FS-2 T11/1619-D Rev 0.90. | 104 | * esb_e_stat - flags from FC-FS-2 T11/1619-D Rev 0.90. |
105 | */ | 105 | */ |
106 | #define ESB_ST_RESP (1 << 31) /* responder to exchange */ | 106 | #define ESB_ST_RESP (1 << 31) /* responder to exchange */ |
107 | #define ESB_ST_SEQ_INIT (1 << 30) /* port holds sequence initiaive */ | 107 | #define ESB_ST_SEQ_INIT (1 << 30) /* port holds sequence initiative */ |
108 | #define ESB_ST_COMPLETE (1 << 29) /* exchange is complete */ | 108 | #define ESB_ST_COMPLETE (1 << 29) /* exchange is complete */ |
109 | #define ESB_ST_ABNORMAL (1 << 28) /* abnormal ending condition */ | 109 | #define ESB_ST_ABNORMAL (1 << 28) /* abnormal ending condition */ |
110 | #define ESB_ST_REC_QUAL (1 << 26) /* recovery qualifier active */ | 110 | #define ESB_ST_REC_QUAL (1 << 26) /* recovery qualifier active */ |
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 13d81c5c4ebf..5d6ed6cf12cc 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h | |||
@@ -69,6 +69,7 @@ enum iscsi_uevent_e { | |||
69 | ISCSI_UEVENT_LOGIN_FLASHNODE = UEVENT_BASE + 28, | 69 | ISCSI_UEVENT_LOGIN_FLASHNODE = UEVENT_BASE + 28, |
70 | ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29, | 70 | ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29, |
71 | ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30, | 71 | ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30, |
72 | ISCSI_UEVENT_SET_CHAP = UEVENT_BASE + 31, | ||
72 | 73 | ||
73 | /* up events */ | 74 | /* up events */ |
74 | ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, | 75 | ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, |
@@ -309,8 +310,16 @@ enum iscsi_param_type { | |||
309 | ISCSI_HOST_PARAM, /* iscsi_host_param */ | 310 | ISCSI_HOST_PARAM, /* iscsi_host_param */ |
310 | ISCSI_NET_PARAM, /* iscsi_net_param */ | 311 | ISCSI_NET_PARAM, /* iscsi_net_param */ |
311 | ISCSI_FLASHNODE_PARAM, /* iscsi_flashnode_param */ | 312 | ISCSI_FLASHNODE_PARAM, /* iscsi_flashnode_param */ |
313 | ISCSI_CHAP_PARAM, /* iscsi_chap_param */ | ||
312 | }; | 314 | }; |
313 | 315 | ||
316 | /* structure for minimalist usecase */ | ||
317 | struct iscsi_param_info { | ||
318 | uint32_t len; /* Actual length of the param value */ | ||
319 | uint16_t param; /* iscsi param */ | ||
320 | uint8_t value[0]; /* length sized value follows */ | ||
321 | } __packed; | ||
322 | |||
314 | struct iscsi_iface_param_info { | 323 | struct iscsi_iface_param_info { |
315 | uint32_t iface_num; /* iface number, 0 - n */ | 324 | uint32_t iface_num; /* iface number, 0 - n */ |
316 | uint32_t len; /* Actual length of the param */ | 325 | uint32_t len; /* Actual length of the param */ |
@@ -739,6 +748,14 @@ enum chap_type_e { | |||
739 | CHAP_TYPE_IN, | 748 | CHAP_TYPE_IN, |
740 | }; | 749 | }; |
741 | 750 | ||
751 | enum iscsi_chap_param { | ||
752 | ISCSI_CHAP_PARAM_INDEX, | ||
753 | ISCSI_CHAP_PARAM_CHAP_TYPE, | ||
754 | ISCSI_CHAP_PARAM_USERNAME, | ||
755 | ISCSI_CHAP_PARAM_PASSWORD, | ||
756 | ISCSI_CHAP_PARAM_PASSWORD_LEN | ||
757 | }; | ||
758 | |||
742 | #define ISCSI_CHAP_AUTH_NAME_MAX_LEN 256 | 759 | #define ISCSI_CHAP_AUTH_NAME_MAX_LEN 256 |
743 | #define ISCSI_CHAP_AUTH_SECRET_MAX_LEN 256 | 760 | #define ISCSI_CHAP_AUTH_SECRET_MAX_LEN 256 |
744 | struct iscsi_chap_rec { | 761 | struct iscsi_chap_rec { |
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index e1379b4e8faf..52beadf9a29b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h | |||
@@ -410,6 +410,12 @@ struct fc_seq { | |||
410 | * @fh_type: The frame type | 410 | * @fh_type: The frame type |
411 | * @class: The class of service | 411 | * @class: The class of service |
412 | * @seq: The sequence in use on this exchange | 412 | * @seq: The sequence in use on this exchange |
413 | * @resp_active: Number of tasks that are concurrently executing @resp(). | ||
414 | * @resp_task: If @resp_active > 0, either the task executing @resp(), the | ||
415 | * task that has been interrupted to execute the soft-IRQ | ||
416 | * executing @resp() or NULL if more than one task is executing | ||
417 | * @resp concurrently. | ||
418 | * @resp_wq: Waitqueue for the tasks waiting on @resp_active. | ||
413 | * @resp: Callback for responses on this exchange | 419 | * @resp: Callback for responses on this exchange |
414 | * @destructor: Called when destroying the exchange | 420 | * @destructor: Called when destroying the exchange |
415 | * @arg: Passed as a void pointer to the resp() callback | 421 | * @arg: Passed as a void pointer to the resp() callback |
@@ -441,6 +447,9 @@ struct fc_exch { | |||
441 | u32 r_a_tov; | 447 | u32 r_a_tov; |
442 | u32 f_ctl; | 448 | u32 f_ctl; |
443 | struct fc_seq seq; | 449 | struct fc_seq seq; |
450 | int resp_active; | ||
451 | struct task_struct *resp_task; | ||
452 | wait_queue_head_t resp_wq; | ||
444 | void (*resp)(struct fc_seq *, struct fc_frame *, void *); | 453 | void (*resp)(struct fc_seq *, struct fc_frame *, void *); |
445 | void *arg; | 454 | void *arg; |
446 | void (*destructor)(struct fc_seq *, void *); | 455 | void (*destructor)(struct fc_seq *, void *); |
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 4427393115ea..de7e3ee60f0c 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h | |||
@@ -90,6 +90,7 @@ enum fip_state { | |||
90 | * @lp: &fc_lport: libfc local port. | 90 | * @lp: &fc_lport: libfc local port. |
91 | * @sel_fcf: currently selected FCF, or NULL. | 91 | * @sel_fcf: currently selected FCF, or NULL. |
92 | * @fcfs: list of discovered FCFs. | 92 | * @fcfs: list of discovered FCFs. |
93 | * @cdev: (Optional) pointer to sysfs fcoe_ctlr_device. | ||
93 | * @fcf_count: number of discovered FCF entries. | 94 | * @fcf_count: number of discovered FCF entries. |
94 | * @sol_time: time when a multicast solicitation was last sent. | 95 | * @sol_time: time when a multicast solicitation was last sent. |
95 | * @sel_time: time after which to select an FCF. | 96 | * @sel_time: time after which to select an FCF. |
@@ -127,6 +128,7 @@ struct fcoe_ctlr { | |||
127 | struct fc_lport *lp; | 128 | struct fc_lport *lp; |
128 | struct fcoe_fcf *sel_fcf; | 129 | struct fcoe_fcf *sel_fcf; |
129 | struct list_head fcfs; | 130 | struct list_head fcfs; |
131 | struct fcoe_ctlr_device *cdev; | ||
130 | u16 fcf_count; | 132 | u16 fcf_count; |
131 | unsigned long sol_time; | 133 | unsigned long sol_time; |
132 | unsigned long sel_time; | 134 | unsigned long sel_time; |
@@ -168,8 +170,11 @@ static inline void *fcoe_ctlr_priv(const struct fcoe_ctlr *ctlr) | |||
168 | return (void *)(ctlr + 1); | 170 | return (void *)(ctlr + 1); |
169 | } | 171 | } |
170 | 172 | ||
173 | /* | ||
174 | * This assumes that the fcoe_ctlr (x) is allocated with the fcoe_ctlr_device. | ||
175 | */ | ||
171 | #define fcoe_ctlr_to_ctlr_dev(x) \ | 176 | #define fcoe_ctlr_to_ctlr_dev(x) \ |
172 | (struct fcoe_ctlr_device *)(((struct fcoe_ctlr_device *)(x)) - 1) | 177 | (x)->cdev |
173 | 178 | ||
174 | /** | 179 | /** |
175 | * struct fcoe_fcf - Fibre-Channel Forwarder | 180 | * struct fcoe_fcf - Fibre-Channel Forwarder |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 755243572219..546084964d55 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -598,9 +598,12 @@ struct Scsi_Host { | |||
598 | unsigned int host_eh_scheduled; /* EH scheduled without command */ | 598 | unsigned int host_eh_scheduled; /* EH scheduled without command */ |
599 | 599 | ||
600 | unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ | 600 | unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ |
601 | int resetting; /* if set, it means that last_reset is a valid value */ | 601 | |
602 | /* next two fields are used to bound the time spent in error handling */ | ||
603 | int eh_deadline; | ||
602 | unsigned long last_reset; | 604 | unsigned long last_reset; |
603 | 605 | ||
606 | |||
604 | /* | 607 | /* |
605 | * These three parameters can be used to allow for wide scsi, | 608 | * These three parameters can be used to allow for wide scsi, |
606 | * and for host adapters that support multiple busses | 609 | * and for host adapters that support multiple busses |
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index d0f1602985e7..fe7c8f3e93f8 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -152,6 +152,7 @@ struct iscsi_transport { | |||
152 | int (*get_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx, | 152 | int (*get_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx, |
153 | uint32_t *num_entries, char *buf); | 153 | uint32_t *num_entries, char *buf); |
154 | int (*delete_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx); | 154 | int (*delete_chap) (struct Scsi_Host *shost, uint16_t chap_tbl_idx); |
155 | int (*set_chap) (struct Scsi_Host *shost, void *data, int len); | ||
155 | int (*get_flashnode_param) (struct iscsi_bus_flash_session *fnode_sess, | 156 | int (*get_flashnode_param) (struct iscsi_bus_flash_session *fnode_sess, |
156 | int param, char *buf); | 157 | int param, char *buf); |
157 | int (*set_flashnode_param) (struct iscsi_bus_flash_session *fnode_sess, | 158 | int (*set_flashnode_param) (struct iscsi_bus_flash_session *fnode_sess, |