diff options
79 files changed, 5888 insertions, 1225 deletions
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 4d9ce73ff730..9ed1d9d96783 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | Release Date : Wed. May 11, 2011 17:00:00 PST 2010 - | ||
| 2 | (emaild-id:megaraidlinux@lsi.com) | ||
| 3 | Adam Radford | ||
| 4 | Current Version : 00.00.05.38-rc1 | ||
| 5 | Old Version : 00.00.05.34-rc1 | ||
| 6 | 1. Remove MSI-X black list, use MFI_REG_STATE.ready.msiEnable. | ||
| 7 | 2. Remove un-used function megasas_return_cmd_for_smid(). | ||
| 8 | 3. Check MFI_REG_STATE.fault.resetAdapter in megasas_reset_fusion(). | ||
| 9 | 4. Disable interrupts/free_irq() in megasas_shutdown(). | ||
| 10 | 5. Fix bug where AENs could be lost in probe() and resume(). | ||
| 11 | 6. Convert 6,10,12 byte CDB's to 16 byte CDB for large LBA's for FastPath | ||
| 12 | IO. | ||
| 13 | 7. Add 1078 OCR support. | ||
| 14 | ------------------------------------------------------------------------------- | ||
| 1 | Release Date : Thu. Feb 24, 2011 17:00:00 PST 2010 - | 15 | Release Date : Thu. Feb 24, 2011 17:00:00 PST 2010 - |
| 2 | (emaild-id:megaraidlinux@lsi.com) | 16 | (emaild-id:megaraidlinux@lsi.com) |
| 3 | Adam Radford | 17 | Adam Radford |
diff --git a/MAINTAINERS b/MAINTAINERS index a33b11560d3f..b9f5aee36375 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5515,7 +5515,7 @@ F: drivers/scsi/sg.c | |||
| 5515 | F: include/scsi/sg.h | 5515 | F: include/scsi/sg.h |
| 5516 | 5516 | ||
| 5517 | SCSI SUBSYSTEM | 5517 | SCSI SUBSYSTEM |
| 5518 | M: "James E.J. Bottomley" <James.Bottomley@suse.de> | 5518 | M: "James E.J. Bottomley" <JBottomley@parallels.com> |
| 5519 | L: linux-scsi@vger.kernel.org | 5519 | L: linux-scsi@vger.kernel.org |
| 5520 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git | 5520 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git |
| 5521 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git | 5521 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git |
| @@ -6084,6 +6084,17 @@ F: Documentation/filesystems/sysv-fs.txt | |||
| 6084 | F: fs/sysv/ | 6084 | F: fs/sysv/ |
| 6085 | F: include/linux/sysv_fs.h | 6085 | F: include/linux/sysv_fs.h |
| 6086 | 6086 | ||
| 6087 | TARGET SUBSYSTEM | ||
| 6088 | M: Nicholas A. Bellinger <nab@linux-iscsi.org> | ||
| 6089 | L: linux-scsi@vger.kernel.org | ||
| 6090 | L: http://groups.google.com/group/linux-iscsi-target-dev | ||
| 6091 | W: http://www.linux-iscsi.org | ||
| 6092 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core-2.6.git master | ||
| 6093 | S: Supported | ||
| 6094 | F: drivers/target/ | ||
| 6095 | F: include/target/ | ||
| 6096 | F: Documentation/target/ | ||
| 6097 | |||
| 6087 | TASKSTATS STATISTICS INTERFACE | 6098 | TASKSTATS STATISTICS INTERFACE |
| 6088 | M: Balbir Singh <balbir@linux.vnet.ibm.com> | 6099 | M: Balbir Singh <balbir@linux.vnet.ibm.com> |
| 6089 | S: Maintained | 6100 | S: Maintained |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 3b7e83d2dab4..d5ff142c93a2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
| @@ -486,7 +486,7 @@ static ssize_t asd_show_update_bios(struct device *dev, | |||
| 486 | flash_error_table[i].reason); | 486 | flash_error_table[i].reason); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUGO, | 489 | static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUSR, |
| 490 | asd_show_update_bios, asd_store_update_bios); | 490 | asd_show_update_bios, asd_store_update_bios); |
| 491 | 491 | ||
| 492 | static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha) | 492 | static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha) |
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c1f72c49196f..6c7e0339dda4 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
| @@ -56,6 +56,8 @@ BFA_TRC_FILE(CNA, IOC); | |||
| 56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) | 56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) |
| 57 | #define bfa_ioc_notify_fail(__ioc) \ | 57 | #define bfa_ioc_notify_fail(__ioc) \ |
| 58 | ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) | 58 | ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) |
| 59 | #define bfa_ioc_sync_start(__ioc) \ | ||
| 60 | ((__ioc)->ioc_hwif->ioc_sync_start(__ioc)) | ||
| 59 | #define bfa_ioc_sync_join(__ioc) \ | 61 | #define bfa_ioc_sync_join(__ioc) \ |
| 60 | ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) | 62 | ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) |
| 61 | #define bfa_ioc_sync_leave(__ioc) \ | 63 | #define bfa_ioc_sync_leave(__ioc) \ |
| @@ -647,7 +649,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
| 647 | switch (event) { | 649 | switch (event) { |
| 648 | case IOCPF_E_SEMLOCKED: | 650 | case IOCPF_E_SEMLOCKED: |
| 649 | if (bfa_ioc_firmware_lock(ioc)) { | 651 | if (bfa_ioc_firmware_lock(ioc)) { |
| 650 | if (bfa_ioc_sync_complete(ioc)) { | 652 | if (bfa_ioc_sync_start(ioc)) { |
| 651 | iocpf->retry_count = 0; | 653 | iocpf->retry_count = 0; |
| 652 | bfa_ioc_sync_join(ioc); | 654 | bfa_ioc_sync_join(ioc); |
| 653 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | 655 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); |
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index ec9cf08b0e7f..c85182a704fb 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h | |||
| @@ -263,6 +263,7 @@ struct bfa_ioc_hwif_s { | |||
| 263 | bfa_boolean_t msix); | 263 | bfa_boolean_t msix); |
| 264 | void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); | 264 | void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); |
| 265 | void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); | 265 | void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); |
| 266 | bfa_boolean_t (*ioc_sync_start) (struct bfa_ioc_s *ioc); | ||
| 266 | void (*ioc_sync_join) (struct bfa_ioc_s *ioc); | 267 | void (*ioc_sync_join) (struct bfa_ioc_s *ioc); |
| 267 | void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); | 268 | void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); |
| 268 | void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); | 269 | void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); |
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index e4a0713185b6..89ae4c8f95a2 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c | |||
| @@ -32,6 +32,7 @@ static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); | |||
| 32 | static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); | 32 | static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); |
| 33 | static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); | 33 | static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); |
| 34 | static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); | 34 | static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); |
| 35 | static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc); | ||
| 35 | static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); | 36 | static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); |
| 36 | static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); | 37 | static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); |
| 37 | static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); | 38 | static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); |
| @@ -53,6 +54,7 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) | |||
| 53 | hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; | 54 | hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; |
| 54 | hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; | 55 | hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; |
| 55 | hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; | 56 | hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; |
| 57 | hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start; | ||
| 56 | hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; | 58 | hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; |
| 57 | hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; | 59 | hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; |
| 58 | hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; | 60 | hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; |
| @@ -195,6 +197,15 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) | |||
| 195 | } | 197 | } |
| 196 | 198 | ||
| 197 | /* | 199 | /* |
| 200 | * Synchronized IOC failure processing routines | ||
| 201 | */ | ||
| 202 | static bfa_boolean_t | ||
| 203 | bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) | ||
| 204 | { | ||
| 205 | return bfa_ioc_cb_sync_complete(ioc); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* | ||
| 198 | * Cleanup hw semaphore and usecnt registers | 209 | * Cleanup hw semaphore and usecnt registers |
| 199 | */ | 210 | */ |
| 200 | static void | 211 | static void |
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 008d129ddfcd..93612520f0d2 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c | |||
| @@ -41,6 +41,7 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); | |||
| 41 | static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); | 41 | static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); |
| 42 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); | 42 | static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); |
| 43 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); | 43 | static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); |
| 44 | static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc); | ||
| 44 | static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); | 45 | static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); |
| 45 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); | 46 | static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); |
| 46 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); | 47 | static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); |
| @@ -62,6 +63,7 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) | |||
| 62 | hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; | 63 | hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; |
| 63 | hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; | 64 | hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; |
| 64 | hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; | 65 | hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; |
| 66 | hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start; | ||
| 65 | hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; | 67 | hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; |
| 66 | hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; | 68 | hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; |
| 67 | hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; | 69 | hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; |
| @@ -351,6 +353,30 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) | |||
| 351 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 353 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
| 352 | } | 354 | } |
| 353 | 355 | ||
| 356 | static bfa_boolean_t | ||
| 357 | bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc) | ||
| 358 | { | ||
| 359 | uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); | ||
| 360 | uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); | ||
| 361 | |||
| 362 | /* | ||
| 363 | * Driver load time. If the sync required bit for this PCI fn | ||
| 364 | * is set, it is due to an unclean exit by the driver for this | ||
| 365 | * PCI fn in the previous incarnation. Whoever comes here first | ||
| 366 | * should clean it up, no matter which PCI fn. | ||
| 367 | */ | ||
| 368 | |||
| 369 | if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { | ||
| 370 | writel(0, ioc->ioc_regs.ioc_fail_sync); | ||
| 371 | writel(1, ioc->ioc_regs.ioc_usage_reg); | ||
| 372 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | ||
| 373 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | ||
| 374 | return BFA_TRUE; | ||
| 375 | } | ||
| 376 | |||
| 377 | return bfa_ioc_ct_sync_complete(ioc); | ||
| 378 | } | ||
| 379 | |||
| 354 | /* | 380 | /* |
| 355 | * Synchronized IOC failure processing routines | 381 | * Synchronized IOC failure processing routines |
| 356 | */ | 382 | */ |
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index cfd59023227b..6bdd25a93db9 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h | |||
| @@ -66,11 +66,11 @@ | |||
| 66 | #define BD_SPLIT_SIZE 32768 | 66 | #define BD_SPLIT_SIZE 32768 |
| 67 | 67 | ||
| 68 | /* min, max & default values for SQ/RQ/CQ size, configurable via' modparam */ | 68 | /* min, max & default values for SQ/RQ/CQ size, configurable via' modparam */ |
| 69 | #define BNX2I_SQ_WQES_MIN 16 | 69 | #define BNX2I_SQ_WQES_MIN 16 |
| 70 | #define BNX2I_570X_SQ_WQES_MAX 128 | 70 | #define BNX2I_570X_SQ_WQES_MAX 128 |
| 71 | #define BNX2I_5770X_SQ_WQES_MAX 512 | 71 | #define BNX2I_5770X_SQ_WQES_MAX 512 |
| 72 | #define BNX2I_570X_SQ_WQES_DEFAULT 128 | 72 | #define BNX2I_570X_SQ_WQES_DEFAULT 128 |
| 73 | #define BNX2I_5770X_SQ_WQES_DEFAULT 256 | 73 | #define BNX2I_5770X_SQ_WQES_DEFAULT 128 |
| 74 | 74 | ||
| 75 | #define BNX2I_570X_CQ_WQES_MAX 128 | 75 | #define BNX2I_570X_CQ_WQES_MAX 128 |
| 76 | #define BNX2I_5770X_CQ_WQES_MAX 512 | 76 | #define BNX2I_5770X_CQ_WQES_MAX 512 |
| @@ -115,6 +115,7 @@ | |||
| 115 | #define BNX2X_MAX_CQS 8 | 115 | #define BNX2X_MAX_CQS 8 |
| 116 | 116 | ||
| 117 | #define CNIC_ARM_CQE 1 | 117 | #define CNIC_ARM_CQE 1 |
| 118 | #define CNIC_ARM_CQE_FP 2 | ||
| 118 | #define CNIC_DISARM_CQE 0 | 119 | #define CNIC_DISARM_CQE 0 |
| 119 | 120 | ||
| 120 | #define REG_RD(__hba, offset) \ | 121 | #define REG_RD(__hba, offset) \ |
| @@ -666,7 +667,9 @@ enum { | |||
| 666 | * after HBA reset is completed by bnx2i/cnic/bnx2 | 667 | * after HBA reset is completed by bnx2i/cnic/bnx2 |
| 667 | * modules | 668 | * modules |
| 668 | * @state: tracks offload connection state machine | 669 | * @state: tracks offload connection state machine |
| 669 | * @teardown_mode: indicates if conn teardown is abortive or orderly | 670 | * @timestamp: tracks the start time when the ep begins to connect |
| 671 | * @num_active_cmds: tracks the number of outstanding commands for this ep | ||
| 672 | * @ec_shift: the amount of shift as part of the event coal calc | ||
| 670 | * @qp: QP information | 673 | * @qp: QP information |
| 671 | * @ids: contains chip allocated *context id* & driver assigned | 674 | * @ids: contains chip allocated *context id* & driver assigned |
| 672 | * *iscsi cid* | 675 | * *iscsi cid* |
| @@ -685,6 +688,7 @@ struct bnx2i_endpoint { | |||
| 685 | u32 state; | 688 | u32 state; |
| 686 | unsigned long timestamp; | 689 | unsigned long timestamp; |
| 687 | int num_active_cmds; | 690 | int num_active_cmds; |
| 691 | u32 ec_shift; | ||
| 688 | 692 | ||
| 689 | struct qp_info qp; | 693 | struct qp_info qp; |
| 690 | struct ep_handles ids; | 694 | struct ep_handles ids; |
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index f0b89513faed..5c54a2d9b834 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
| @@ -138,7 +138,6 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) | |||
| 138 | u16 next_index; | 138 | u16 next_index; |
| 139 | u32 num_active_cmds; | 139 | u32 num_active_cmds; |
| 140 | 140 | ||
| 141 | |||
| 142 | /* Coalesce CQ entries only on 10G devices */ | 141 | /* Coalesce CQ entries only on 10G devices */ |
| 143 | if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) | 142 | if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) |
| 144 | return; | 143 | return; |
| @@ -148,16 +147,19 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) | |||
| 148 | * interrupts and other unwanted results | 147 | * interrupts and other unwanted results |
| 149 | */ | 148 | */ |
| 150 | cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt; | 149 | cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt; |
| 151 | if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF) | ||
| 152 | return; | ||
| 153 | 150 | ||
| 154 | if (action == CNIC_ARM_CQE) { | 151 | if (action != CNIC_ARM_CQE_FP) |
| 152 | if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF) | ||
| 153 | return; | ||
| 154 | |||
| 155 | if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) { | ||
| 155 | num_active_cmds = ep->num_active_cmds; | 156 | num_active_cmds = ep->num_active_cmds; |
| 156 | if (num_active_cmds <= event_coal_min) | 157 | if (num_active_cmds <= event_coal_min) |
| 157 | next_index = 1; | 158 | next_index = 1; |
| 158 | else | 159 | else |
| 159 | next_index = event_coal_min + | 160 | next_index = event_coal_min + |
| 160 | (num_active_cmds - event_coal_min) / event_coal_div; | 161 | ((num_active_cmds - event_coal_min) >> |
| 162 | ep->ec_shift); | ||
| 161 | if (!next_index) | 163 | if (!next_index) |
| 162 | next_index = 1; | 164 | next_index = 1; |
| 163 | cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1; | 165 | cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1; |
| @@ -1274,6 +1276,7 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) | |||
| 1274 | iscsi_init.dummy_buffer_addr_hi = | 1276 | iscsi_init.dummy_buffer_addr_hi = |
| 1275 | (u32) ((u64) hba->dummy_buf_dma >> 32); | 1277 | (u32) ((u64) hba->dummy_buf_dma >> 32); |
| 1276 | 1278 | ||
| 1279 | hba->num_ccell = hba->max_sqes >> 1; | ||
| 1277 | hba->ctx_ccell_tasks = | 1280 | hba->ctx_ccell_tasks = |
| 1278 | ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16)); | 1281 | ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16)); |
| 1279 | iscsi_init.num_ccells_per_conn = hba->num_ccell; | 1282 | iscsi_init.num_ccells_per_conn = hba->num_ccell; |
| @@ -1934,7 +1937,6 @@ cqe_out: | |||
| 1934 | qp->cq_cons_idx++; | 1937 | qp->cq_cons_idx++; |
| 1935 | } | 1938 | } |
| 1936 | } | 1939 | } |
| 1937 | bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE); | ||
| 1938 | } | 1940 | } |
| 1939 | 1941 | ||
| 1940 | /** | 1942 | /** |
| @@ -1948,22 +1950,23 @@ cqe_out: | |||
| 1948 | static void bnx2i_fastpath_notification(struct bnx2i_hba *hba, | 1950 | static void bnx2i_fastpath_notification(struct bnx2i_hba *hba, |
| 1949 | struct iscsi_kcqe *new_cqe_kcqe) | 1951 | struct iscsi_kcqe *new_cqe_kcqe) |
| 1950 | { | 1952 | { |
| 1951 | struct bnx2i_conn *conn; | 1953 | struct bnx2i_conn *bnx2i_conn; |
| 1952 | u32 iscsi_cid; | 1954 | u32 iscsi_cid; |
| 1953 | 1955 | ||
| 1954 | iscsi_cid = new_cqe_kcqe->iscsi_conn_id; | 1956 | iscsi_cid = new_cqe_kcqe->iscsi_conn_id; |
| 1955 | conn = bnx2i_get_conn_from_id(hba, iscsi_cid); | 1957 | bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid); |
| 1956 | 1958 | ||
| 1957 | if (!conn) { | 1959 | if (!bnx2i_conn) { |
| 1958 | printk(KERN_ALERT "cid #%x not valid\n", iscsi_cid); | 1960 | printk(KERN_ALERT "cid #%x not valid\n", iscsi_cid); |
| 1959 | return; | 1961 | return; |
| 1960 | } | 1962 | } |
| 1961 | if (!conn->ep) { | 1963 | if (!bnx2i_conn->ep) { |
| 1962 | printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); | 1964 | printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); |
| 1963 | return; | 1965 | return; |
| 1964 | } | 1966 | } |
| 1965 | 1967 | bnx2i_process_new_cqes(bnx2i_conn); | |
| 1966 | bnx2i_process_new_cqes(conn); | 1968 | bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP); |
| 1969 | bnx2i_process_new_cqes(bnx2i_conn); | ||
| 1967 | } | 1970 | } |
| 1968 | 1971 | ||
| 1969 | 1972 | ||
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 1d24a2819736..6adbdc34a9a5 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c | |||
| @@ -244,7 +244,7 @@ void bnx2i_stop(void *handle) | |||
| 244 | wait_event_interruptible_timeout(hba->eh_wait, | 244 | wait_event_interruptible_timeout(hba->eh_wait, |
| 245 | (list_empty(&hba->ep_ofld_list) && | 245 | (list_empty(&hba->ep_ofld_list) && |
| 246 | list_empty(&hba->ep_destroy_list)), | 246 | list_empty(&hba->ep_destroy_list)), |
| 247 | 10 * HZ); | 247 | 2 * HZ); |
| 248 | /* Wait for all endpoints to be torn down, Chip will be reset once | 248 | /* Wait for all endpoints to be torn down, Chip will be reset once |
| 249 | * control returns to network driver. So it is required to cleanup and | 249 | * control returns to network driver. So it is required to cleanup and |
| 250 | * release all connection resources before returning from this routine. | 250 | * release all connection resources before returning from this routine. |
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 1809f9ccc4ce..041928b23cb0 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
| @@ -379,6 +379,7 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) | |||
| 379 | { | 379 | { |
| 380 | struct iscsi_endpoint *ep; | 380 | struct iscsi_endpoint *ep; |
| 381 | struct bnx2i_endpoint *bnx2i_ep; | 381 | struct bnx2i_endpoint *bnx2i_ep; |
| 382 | u32 ec_div; | ||
| 382 | 383 | ||
| 383 | ep = iscsi_create_endpoint(sizeof(*bnx2i_ep)); | 384 | ep = iscsi_create_endpoint(sizeof(*bnx2i_ep)); |
| 384 | if (!ep) { | 385 | if (!ep) { |
| @@ -393,6 +394,11 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) | |||
| 393 | bnx2i_ep->ep_iscsi_cid = (u16) -1; | 394 | bnx2i_ep->ep_iscsi_cid = (u16) -1; |
| 394 | bnx2i_ep->hba = hba; | 395 | bnx2i_ep->hba = hba; |
| 395 | bnx2i_ep->hba_age = hba->age; | 396 | bnx2i_ep->hba_age = hba->age; |
| 397 | |||
| 398 | ec_div = event_coal_div; | ||
| 399 | while (ec_div >>= 1) | ||
| 400 | bnx2i_ep->ec_shift += 1; | ||
| 401 | |||
| 396 | hba->ofld_conns_active++; | 402 | hba->ofld_conns_active++; |
| 397 | init_waitqueue_head(&bnx2i_ep->ofld_wait); | 403 | init_waitqueue_head(&bnx2i_ep->ofld_wait); |
| 398 | return ep; | 404 | return ep; |
| @@ -858,7 +864,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) | |||
| 858 | mutex_init(&hba->net_dev_lock); | 864 | mutex_init(&hba->net_dev_lock); |
| 859 | init_waitqueue_head(&hba->eh_wait); | 865 | init_waitqueue_head(&hba->eh_wait); |
| 860 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { | 866 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) { |
| 861 | hba->hba_shutdown_tmo = 20 * HZ; | 867 | hba->hba_shutdown_tmo = 30 * HZ; |
| 862 | hba->conn_teardown_tmo = 20 * HZ; | 868 | hba->conn_teardown_tmo = 20 * HZ; |
| 863 | hba->conn_ctx_destroy_tmo = 6 * HZ; | 869 | hba->conn_ctx_destroy_tmo = 6 * HZ; |
| 864 | } else { /* 5706/5708/5709 */ | 870 | } else { /* 5706/5708/5709 */ |
| @@ -1208,6 +1214,9 @@ static int bnx2i_task_xmit(struct iscsi_task *task) | |||
| 1208 | struct bnx2i_cmd *cmd = task->dd_data; | 1214 | struct bnx2i_cmd *cmd = task->dd_data; |
| 1209 | struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr; | 1215 | struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr; |
| 1210 | 1216 | ||
| 1217 | if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes) | ||
| 1218 | return -ENOMEM; | ||
| 1219 | |||
| 1211 | /* | 1220 | /* |
| 1212 | * If there is no scsi_cmnd this must be a mgmt task | 1221 | * If there is no scsi_cmnd this must be a mgmt task |
| 1213 | */ | 1222 | */ |
| @@ -2156,7 +2165,7 @@ static struct scsi_host_template bnx2i_host_template = { | |||
| 2156 | .change_queue_depth = iscsi_change_queue_depth, | 2165 | .change_queue_depth = iscsi_change_queue_depth, |
| 2157 | .can_queue = 1024, | 2166 | .can_queue = 1024, |
| 2158 | .max_sectors = 127, | 2167 | .max_sectors = 127, |
| 2159 | .cmd_per_lun = 32, | 2168 | .cmd_per_lun = 24, |
| 2160 | .this_id = -1, | 2169 | .this_id = -1, |
| 2161 | .use_clustering = ENABLE_CLUSTERING, | 2170 | .use_clustering = ENABLE_CLUSTERING, |
| 2162 | .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, | 2171 | .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cc23bd9480b2..155d7b9bdeae 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
| @@ -137,6 +137,7 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); | |||
| 137 | static int fcoe_vport_disable(struct fc_vport *, bool disable); | 137 | static int fcoe_vport_disable(struct fc_vport *, bool disable); |
| 138 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 138 | static void fcoe_set_vport_symbolic_name(struct fc_vport *); |
| 139 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); | 139 | static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); |
| 140 | static int fcoe_validate_vport_create(struct fc_vport *); | ||
| 140 | 141 | ||
| 141 | static struct libfc_function_template fcoe_libfc_fcn_templ = { | 142 | static struct libfc_function_template fcoe_libfc_fcn_templ = { |
| 142 | .frame_send = fcoe_xmit, | 143 | .frame_send = fcoe_xmit, |
| @@ -2351,6 +2352,17 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) | |||
| 2351 | struct fcoe_interface *fcoe = port->priv; | 2352 | struct fcoe_interface *fcoe = port->priv; |
| 2352 | struct net_device *netdev = fcoe->netdev; | 2353 | struct net_device *netdev = fcoe->netdev; |
| 2353 | struct fc_lport *vn_port; | 2354 | struct fc_lport *vn_port; |
| 2355 | int rc; | ||
| 2356 | char buf[32]; | ||
| 2357 | |||
| 2358 | rc = fcoe_validate_vport_create(vport); | ||
| 2359 | if (rc) { | ||
| 2360 | wwn_to_str(vport->port_name, buf, sizeof(buf)); | ||
| 2361 | printk(KERN_ERR "fcoe: Failed to create vport, " | ||
| 2362 | "WWPN (0x%s) already exists\n", | ||
| 2363 | buf); | ||
| 2364 | return rc; | ||
| 2365 | } | ||
| 2354 | 2366 | ||
| 2355 | mutex_lock(&fcoe_config_mutex); | 2367 | mutex_lock(&fcoe_config_mutex); |
| 2356 | vn_port = fcoe_if_create(fcoe, &vport->dev, 1); | 2368 | vn_port = fcoe_if_create(fcoe, &vport->dev, 1); |
| @@ -2497,3 +2509,49 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
| 2497 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2509 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
| 2498 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2510 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); |
| 2499 | } | 2511 | } |
| 2512 | |||
| 2513 | /** | ||
| 2514 | * fcoe_validate_vport_create() - Validate a vport before creating it | ||
| 2515 | * @vport: NPIV port to be created | ||
| 2516 | * | ||
| 2517 | * This routine is meant to add validation for a vport before creating it | ||
| 2518 | * via fcoe_vport_create(). | ||
| 2519 | * Current validations are: | ||
| 2520 | * - WWPN supplied is unique for given lport | ||
| 2521 | * | ||
| 2522 | * | ||
| 2523 | */ | ||
| 2524 | static int fcoe_validate_vport_create(struct fc_vport *vport) | ||
| 2525 | { | ||
| 2526 | struct Scsi_Host *shost = vport_to_shost(vport); | ||
| 2527 | struct fc_lport *n_port = shost_priv(shost); | ||
| 2528 | struct fc_lport *vn_port; | ||
| 2529 | int rc = 0; | ||
| 2530 | char buf[32]; | ||
| 2531 | |||
| 2532 | mutex_lock(&n_port->lp_mutex); | ||
| 2533 | |||
| 2534 | wwn_to_str(vport->port_name, buf, sizeof(buf)); | ||
| 2535 | /* Check if the wwpn is not same as that of the lport */ | ||
| 2536 | if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) { | ||
| 2537 | FCOE_DBG("vport WWPN 0x%s is same as that of the " | ||
| 2538 | "base port WWPN\n", buf); | ||
| 2539 | rc = -EINVAL; | ||
| 2540 | goto out; | ||
| 2541 | } | ||
| 2542 | |||
| 2543 | /* Check if there is any existing vport with same wwpn */ | ||
| 2544 | list_for_each_entry(vn_port, &n_port->vports, list) { | ||
| 2545 | if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) { | ||
| 2546 | FCOE_DBG("vport with given WWPN 0x%s already " | ||
| 2547 | "exists\n", buf); | ||
| 2548 | rc = -EINVAL; | ||
| 2549 | break; | ||
| 2550 | } | ||
| 2551 | } | ||
| 2552 | |||
| 2553 | out: | ||
| 2554 | mutex_unlock(&n_port->lp_mutex); | ||
| 2555 | |||
| 2556 | return rc; | ||
| 2557 | } | ||
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index 408a6fd78fb4..c4a93993c0cf 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
| @@ -99,4 +99,14 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) | |||
| 99 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; | 99 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static inline void wwn_to_str(u64 wwn, char *buf, int len) | ||
| 103 | { | ||
| 104 | u8 wwpn[8]; | ||
| 105 | |||
| 106 | u64_to_wwn(wwn, wwpn); | ||
| 107 | snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x", | ||
| 108 | wwpn[0], wwpn[1], wwpn[2], wwpn[3], | ||
| 109 | wwpn[4], wwpn[5], wwpn[6], wwpn[7]); | ||
| 110 | } | ||
| 111 | |||
| 102 | #endif /* _FCOE_H_ */ | 112 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 229e4af5508a..c74c4b8e71ef 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
| @@ -1173,7 +1173,9 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
| 1173 | struct fc_lport *lport = fip->lp; | 1173 | struct fc_lport *lport = fip->lp; |
| 1174 | struct fc_lport *vn_port = NULL; | 1174 | struct fc_lport *vn_port = NULL; |
| 1175 | u32 desc_mask; | 1175 | u32 desc_mask; |
| 1176 | int is_vn_port = 0; | 1176 | int num_vlink_desc; |
| 1177 | int reset_phys_port = 0; | ||
| 1178 | struct fip_vn_desc **vlink_desc_arr = NULL; | ||
| 1177 | 1179 | ||
| 1178 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); | 1180 | LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); |
| 1179 | 1181 | ||
| @@ -1183,70 +1185,73 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
| 1183 | /* | 1185 | /* |
| 1184 | * mask of required descriptors. Validating each one clears its bit. | 1186 | * mask of required descriptors. Validating each one clears its bit. |
| 1185 | */ | 1187 | */ |
| 1186 | desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID); | 1188 | desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME); |
| 1187 | 1189 | ||
| 1188 | rlen = ntohs(fh->fip_dl_len) * FIP_BPW; | 1190 | rlen = ntohs(fh->fip_dl_len) * FIP_BPW; |
| 1189 | desc = (struct fip_desc *)(fh + 1); | 1191 | desc = (struct fip_desc *)(fh + 1); |
| 1192 | |||
| 1193 | /* | ||
| 1194 | * Actually need to subtract 'sizeof(*mp) - sizeof(*wp)' from 'rlen' | ||
| 1195 | * before determining max Vx_Port descriptor but a buggy FCF could have | ||
| 1196 | * omited either or both MAC Address and Name Identifier descriptors | ||
| 1197 | */ | ||
| 1198 | num_vlink_desc = rlen / sizeof(*vp); | ||
| 1199 | if (num_vlink_desc) | ||
| 1200 | vlink_desc_arr = kmalloc(sizeof(vp) * num_vlink_desc, | ||
| 1201 | GFP_ATOMIC); | ||
| 1202 | if (!vlink_desc_arr) | ||
| 1203 | return; | ||
| 1204 | num_vlink_desc = 0; | ||
| 1205 | |||
| 1190 | while (rlen >= sizeof(*desc)) { | 1206 | while (rlen >= sizeof(*desc)) { |
| 1191 | dlen = desc->fip_dlen * FIP_BPW; | 1207 | dlen = desc->fip_dlen * FIP_BPW; |
| 1192 | if (dlen > rlen) | 1208 | if (dlen > rlen) |
| 1193 | return; | 1209 | goto err; |
| 1194 | /* Drop CVL if there are duplicate critical descriptors */ | 1210 | /* Drop CVL if there are duplicate critical descriptors */ |
| 1195 | if ((desc->fip_dtype < 32) && | 1211 | if ((desc->fip_dtype < 32) && |
| 1212 | (desc->fip_dtype != FIP_DT_VN_ID) && | ||
| 1196 | !(desc_mask & 1U << desc->fip_dtype)) { | 1213 | !(desc_mask & 1U << desc->fip_dtype)) { |
| 1197 | LIBFCOE_FIP_DBG(fip, "Duplicate Critical " | 1214 | LIBFCOE_FIP_DBG(fip, "Duplicate Critical " |
| 1198 | "Descriptors in FIP CVL\n"); | 1215 | "Descriptors in FIP CVL\n"); |
| 1199 | return; | 1216 | goto err; |
| 1200 | } | 1217 | } |
| 1201 | switch (desc->fip_dtype) { | 1218 | switch (desc->fip_dtype) { |
| 1202 | case FIP_DT_MAC: | 1219 | case FIP_DT_MAC: |
| 1203 | mp = (struct fip_mac_desc *)desc; | 1220 | mp = (struct fip_mac_desc *)desc; |
| 1204 | if (dlen < sizeof(*mp)) | 1221 | if (dlen < sizeof(*mp)) |
| 1205 | return; | 1222 | goto err; |
| 1206 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) | 1223 | if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) |
| 1207 | return; | 1224 | goto err; |
| 1208 | desc_mask &= ~BIT(FIP_DT_MAC); | 1225 | desc_mask &= ~BIT(FIP_DT_MAC); |
| 1209 | break; | 1226 | break; |
| 1210 | case FIP_DT_NAME: | 1227 | case FIP_DT_NAME: |
| 1211 | wp = (struct fip_wwn_desc *)desc; | 1228 | wp = (struct fip_wwn_desc *)desc; |
| 1212 | if (dlen < sizeof(*wp)) | 1229 | if (dlen < sizeof(*wp)) |
| 1213 | return; | 1230 | goto err; |
| 1214 | if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name) | 1231 | if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name) |
| 1215 | return; | 1232 | goto err; |
| 1216 | desc_mask &= ~BIT(FIP_DT_NAME); | 1233 | desc_mask &= ~BIT(FIP_DT_NAME); |
| 1217 | break; | 1234 | break; |
| 1218 | case FIP_DT_VN_ID: | 1235 | case FIP_DT_VN_ID: |
| 1219 | vp = (struct fip_vn_desc *)desc; | 1236 | vp = (struct fip_vn_desc *)desc; |
| 1220 | if (dlen < sizeof(*vp)) | 1237 | if (dlen < sizeof(*vp)) |
| 1221 | return; | 1238 | goto err; |
| 1222 | if (compare_ether_addr(vp->fd_mac, | 1239 | vlink_desc_arr[num_vlink_desc++] = vp; |
| 1223 | fip->get_src_addr(lport)) == 0 && | 1240 | vn_port = fc_vport_id_lookup(lport, |
| 1224 | get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn && | 1241 | ntoh24(vp->fd_fc_id)); |
| 1225 | ntoh24(vp->fd_fc_id) == lport->port_id) { | 1242 | if (vn_port && (vn_port == lport)) { |
| 1226 | desc_mask &= ~BIT(FIP_DT_VN_ID); | 1243 | mutex_lock(&fip->ctlr_mutex); |
| 1227 | break; | 1244 | per_cpu_ptr(lport->dev_stats, |
| 1245 | get_cpu())->VLinkFailureCount++; | ||
| 1246 | put_cpu(); | ||
| 1247 | fcoe_ctlr_reset(fip); | ||
| 1248 | mutex_unlock(&fip->ctlr_mutex); | ||
| 1228 | } | 1249 | } |
| 1229 | /* check if clr_vlink is for NPIV port */ | ||
| 1230 | mutex_lock(&lport->lp_mutex); | ||
| 1231 | list_for_each_entry(vn_port, &lport->vports, list) { | ||
| 1232 | if (compare_ether_addr(vp->fd_mac, | ||
| 1233 | fip->get_src_addr(vn_port)) == 0 && | ||
| 1234 | (get_unaligned_be64(&vp->fd_wwpn) | ||
| 1235 | == vn_port->wwpn) && | ||
| 1236 | (ntoh24(vp->fd_fc_id) == | ||
| 1237 | fc_host_port_id(vn_port->host))) { | ||
| 1238 | desc_mask &= ~BIT(FIP_DT_VN_ID); | ||
| 1239 | is_vn_port = 1; | ||
| 1240 | break; | ||
| 1241 | } | ||
| 1242 | } | ||
| 1243 | mutex_unlock(&lport->lp_mutex); | ||
| 1244 | |||
| 1245 | break; | 1250 | break; |
| 1246 | default: | 1251 | default: |
| 1247 | /* standard says ignore unknown descriptors >= 128 */ | 1252 | /* standard says ignore unknown descriptors >= 128 */ |
| 1248 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) | 1253 | if (desc->fip_dtype < FIP_DT_VENDOR_BASE) |
| 1249 | return; | 1254 | goto err; |
| 1250 | break; | 1255 | break; |
| 1251 | } | 1256 | } |
| 1252 | desc = (struct fip_desc *)((char *)desc + dlen); | 1257 | desc = (struct fip_desc *)((char *)desc + dlen); |
| @@ -1256,26 +1261,68 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, | |||
| 1256 | /* | 1261 | /* |
| 1257 | * reset only if all required descriptors were present and valid. | 1262 | * reset only if all required descriptors were present and valid. |
| 1258 | */ | 1263 | */ |
| 1259 | if (desc_mask) { | 1264 | if (desc_mask) |
| 1260 | LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", | 1265 | LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", |
| 1261 | desc_mask); | 1266 | desc_mask); |
| 1267 | else if (!num_vlink_desc) { | ||
| 1268 | LIBFCOE_FIP_DBG(fip, "CVL: no Vx_Port descriptor found\n"); | ||
| 1269 | /* | ||
| 1270 | * No Vx_Port description. Clear all NPIV ports, | ||
| 1271 | * followed by physical port | ||
| 1272 | */ | ||
| 1273 | mutex_lock(&lport->lp_mutex); | ||
| 1274 | list_for_each_entry(vn_port, &lport->vports, list) | ||
| 1275 | fc_lport_reset(vn_port); | ||
| 1276 | mutex_unlock(&lport->lp_mutex); | ||
| 1277 | |||
| 1278 | mutex_lock(&fip->ctlr_mutex); | ||
| 1279 | per_cpu_ptr(lport->dev_stats, | ||
| 1280 | get_cpu())->VLinkFailureCount++; | ||
| 1281 | put_cpu(); | ||
| 1282 | fcoe_ctlr_reset(fip); | ||
| 1283 | mutex_unlock(&fip->ctlr_mutex); | ||
| 1284 | |||
| 1285 | fc_lport_reset(fip->lp); | ||
| 1286 | fcoe_ctlr_solicit(fip, NULL); | ||
| 1262 | } else { | 1287 | } else { |
| 1263 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); | 1288 | int i; |
| 1264 | 1289 | ||
| 1265 | if (is_vn_port) | 1290 | LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); |
| 1266 | fc_lport_reset(vn_port); | 1291 | for (i = 0; i < num_vlink_desc; i++) { |
| 1267 | else { | 1292 | vp = vlink_desc_arr[i]; |
| 1268 | mutex_lock(&fip->ctlr_mutex); | 1293 | vn_port = fc_vport_id_lookup(lport, |
| 1269 | per_cpu_ptr(lport->dev_stats, | 1294 | ntoh24(vp->fd_fc_id)); |
| 1270 | get_cpu())->VLinkFailureCount++; | 1295 | if (!vn_port) |
| 1271 | put_cpu(); | 1296 | continue; |
| 1272 | fcoe_ctlr_reset(fip); | 1297 | |
| 1273 | mutex_unlock(&fip->ctlr_mutex); | 1298 | /* |
| 1299 | * 'port_id' is already validated, check MAC address and | ||
| 1300 | * wwpn | ||
| 1301 | */ | ||
| 1302 | if (compare_ether_addr(fip->get_src_addr(vn_port), | ||
| 1303 | vp->fd_mac) != 0 || | ||
| 1304 | get_unaligned_be64(&vp->fd_wwpn) != | ||
| 1305 | vn_port->wwpn) | ||
| 1306 | continue; | ||
| 1307 | |||
| 1308 | if (vn_port == lport) | ||
| 1309 | /* | ||
| 1310 | * Physical port, defer processing till all | ||
| 1311 | * listed NPIV ports are cleared | ||
| 1312 | */ | ||
| 1313 | reset_phys_port = 1; | ||
| 1314 | else /* NPIV port */ | ||
| 1315 | fc_lport_reset(vn_port); | ||
| 1316 | } | ||
| 1274 | 1317 | ||
| 1318 | if (reset_phys_port) { | ||
| 1275 | fc_lport_reset(fip->lp); | 1319 | fc_lport_reset(fip->lp); |
| 1276 | fcoe_ctlr_solicit(fip, NULL); | 1320 | fcoe_ctlr_solicit(fip, NULL); |
| 1277 | } | 1321 | } |
| 1278 | } | 1322 | } |
| 1323 | |||
| 1324 | err: | ||
| 1325 | kfree(vlink_desc_arr); | ||
| 1279 | } | 1326 | } |
| 1280 | 1327 | ||
| 1281 | /** | 1328 | /** |
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index f81f77c8569e..41068e8748e7 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c | |||
| @@ -544,16 +544,6 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) | |||
| 544 | struct fcoe_transport *ft = NULL; | 544 | struct fcoe_transport *ft = NULL; |
| 545 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; | 545 | enum fip_state fip_mode = (enum fip_state)(long)kp->arg; |
| 546 | 546 | ||
| 547 | #ifdef CONFIG_LIBFCOE_MODULE | ||
| 548 | /* | ||
| 549 | * Make sure the module has been initialized, and is not about to be | ||
| 550 | * removed. Module parameter sysfs files are writable before the | ||
| 551 | * module_init function is called and after module_exit. | ||
| 552 | */ | ||
| 553 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
| 554 | goto out_nodev; | ||
| 555 | #endif | ||
| 556 | |||
| 557 | mutex_lock(&ft_mutex); | 547 | mutex_lock(&ft_mutex); |
| 558 | 548 | ||
| 559 | netdev = fcoe_if_to_netdev(buffer); | 549 | netdev = fcoe_if_to_netdev(buffer); |
| @@ -618,16 +608,6 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) | |||
| 618 | struct net_device *netdev = NULL; | 608 | struct net_device *netdev = NULL; |
| 619 | struct fcoe_transport *ft = NULL; | 609 | struct fcoe_transport *ft = NULL; |
| 620 | 610 | ||
| 621 | #ifdef CONFIG_LIBFCOE_MODULE | ||
| 622 | /* | ||
| 623 | * Make sure the module has been initialized, and is not about to be | ||
| 624 | * removed. Module parameter sysfs files are writable before the | ||
| 625 | * module_init function is called and after module_exit. | ||
| 626 | */ | ||
| 627 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
| 628 | goto out_nodev; | ||
| 629 | #endif | ||
| 630 | |||
| 631 | mutex_lock(&ft_mutex); | 611 | mutex_lock(&ft_mutex); |
| 632 | 612 | ||
| 633 | netdev = fcoe_if_to_netdev(buffer); | 613 | netdev = fcoe_if_to_netdev(buffer); |
| @@ -672,16 +652,6 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) | |||
| 672 | struct net_device *netdev = NULL; | 652 | struct net_device *netdev = NULL; |
| 673 | struct fcoe_transport *ft = NULL; | 653 | struct fcoe_transport *ft = NULL; |
| 674 | 654 | ||
| 675 | #ifdef CONFIG_LIBFCOE_MODULE | ||
| 676 | /* | ||
| 677 | * Make sure the module has been initialized, and is not about to be | ||
| 678 | * removed. Module parameter sysfs files are writable before the | ||
| 679 | * module_init function is called and after module_exit. | ||
| 680 | */ | ||
| 681 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
| 682 | goto out_nodev; | ||
| 683 | #endif | ||
| 684 | |||
| 685 | mutex_lock(&ft_mutex); | 655 | mutex_lock(&ft_mutex); |
| 686 | 656 | ||
| 687 | netdev = fcoe_if_to_netdev(buffer); | 657 | netdev = fcoe_if_to_netdev(buffer); |
| @@ -720,16 +690,6 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) | |||
| 720 | struct net_device *netdev = NULL; | 690 | struct net_device *netdev = NULL; |
| 721 | struct fcoe_transport *ft = NULL; | 691 | struct fcoe_transport *ft = NULL; |
| 722 | 692 | ||
| 723 | #ifdef CONFIG_LIBFCOE_MODULE | ||
| 724 | /* | ||
| 725 | * Make sure the module has been initialized, and is not about to be | ||
| 726 | * removed. Module parameter sysfs files are writable before the | ||
| 727 | * module_init function is called and after module_exit. | ||
| 728 | */ | ||
| 729 | if (THIS_MODULE->state != MODULE_STATE_LIVE) | ||
| 730 | goto out_nodev; | ||
| 731 | #endif | ||
| 732 | |||
| 733 | mutex_lock(&ft_mutex); | 693 | mutex_lock(&ft_mutex); |
| 734 | 694 | ||
| 735 | netdev = fcoe_if_to_netdev(buffer); | 695 | netdev = fcoe_if_to_netdev(buffer); |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 12868ca46110..888086c4e709 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -5149,21 +5149,21 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
| 5149 | 5149 | ||
| 5150 | if (ipr_cmd != NULL) { | 5150 | if (ipr_cmd != NULL) { |
| 5151 | /* Clear the PCI interrupt */ | 5151 | /* Clear the PCI interrupt */ |
| 5152 | num_hrrq = 0; | ||
| 5152 | do { | 5153 | do { |
| 5153 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); | 5154 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); |
| 5154 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5155 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
| 5155 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | 5156 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && |
| 5156 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | 5157 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); |
| 5157 | 5158 | ||
| 5158 | if (int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
| 5159 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
| 5160 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 5161 | return IRQ_HANDLED; | ||
| 5162 | } | ||
| 5163 | |||
| 5164 | } else if (rc == IRQ_NONE && irq_none == 0) { | 5159 | } else if (rc == IRQ_NONE && irq_none == 0) { |
| 5165 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5160 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
| 5166 | irq_none++; | 5161 | irq_none++; |
| 5162 | } else if (num_hrrq == IPR_MAX_HRRQ_RETRIES && | ||
| 5163 | int_reg & IPR_PCII_HRRQ_UPDATED) { | ||
| 5164 | ipr_isr_eh(ioa_cfg, "Error clearing HRRQ"); | ||
| 5165 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 5166 | return IRQ_HANDLED; | ||
| 5167 | } else | 5167 | } else |
| 5168 | break; | 5168 | break; |
| 5169 | } | 5169 | } |
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 911b2736cafa..b9cb8140b398 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c | |||
| @@ -205,6 +205,7 @@ static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp) | |||
| 205 | default: | 205 | default: |
| 206 | FC_DISC_DBG(disc, "Received an unsupported request, " | 206 | FC_DISC_DBG(disc, "Received an unsupported request, " |
| 207 | "the opcode is (%x)\n", op); | 207 | "the opcode is (%x)\n", op); |
| 208 | fc_frame_free(fp); | ||
| 208 | break; | 209 | break; |
| 209 | } | 210 | } |
| 210 | } | 211 | } |
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 77035a746f60..3b8a6451ea28 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
| @@ -1434,6 +1434,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
| 1434 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == | 1434 | (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == |
| 1435 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { | 1435 | (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { |
| 1436 | spin_lock_bh(&ep->ex_lock); | 1436 | spin_lock_bh(&ep->ex_lock); |
| 1437 | resp = ep->resp; | ||
| 1437 | rc = fc_exch_done_locked(ep); | 1438 | rc = fc_exch_done_locked(ep); |
| 1438 | WARN_ON(fc_seq_exch(sp) != ep); | 1439 | WARN_ON(fc_seq_exch(sp) != ep); |
| 1439 | spin_unlock_bh(&ep->ex_lock); | 1440 | spin_unlock_bh(&ep->ex_lock); |
| @@ -1978,6 +1979,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, | |||
| 1978 | spin_unlock_bh(&ep->ex_lock); | 1979 | spin_unlock_bh(&ep->ex_lock); |
| 1979 | return sp; | 1980 | return sp; |
| 1980 | err: | 1981 | err: |
| 1982 | fc_fcp_ddp_done(fr_fsp(fp)); | ||
| 1981 | rc = fc_exch_done_locked(ep); | 1983 | rc = fc_exch_done_locked(ep); |
| 1982 | spin_unlock_bh(&ep->ex_lock); | 1984 | spin_unlock_bh(&ep->ex_lock); |
| 1983 | if (!rc) | 1985 | if (!rc) |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2a3a4720a771..9cd2149519ac 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
| @@ -312,7 +312,7 @@ void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid) | |||
| 312 | * DDP related resources for a fcp_pkt | 312 | * DDP related resources for a fcp_pkt |
| 313 | * @fsp: The FCP packet that DDP had been used on | 313 | * @fsp: The FCP packet that DDP had been used on |
| 314 | */ | 314 | */ |
| 315 | static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) | 315 | void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp) |
| 316 | { | 316 | { |
| 317 | struct fc_lport *lport; | 317 | struct fc_lport *lport; |
| 318 | 318 | ||
| @@ -681,8 +681,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, | |||
| 681 | error = lport->tt.seq_send(lport, seq, fp); | 681 | error = lport->tt.seq_send(lport, seq, fp); |
| 682 | if (error) { | 682 | if (error) { |
| 683 | WARN_ON(1); /* send error should be rare */ | 683 | WARN_ON(1); /* send error should be rare */ |
| 684 | fc_fcp_retry_cmd(fsp); | 684 | return error; |
| 685 | return 0; | ||
| 686 | } | 685 | } |
| 687 | fp = NULL; | 686 | fp = NULL; |
| 688 | } | 687 | } |
| @@ -1673,7 +1672,8 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
| 1673 | FC_FCTL_REQ, 0); | 1672 | FC_FCTL_REQ, 0); |
| 1674 | 1673 | ||
| 1675 | rec_tov = get_fsp_rec_tov(fsp); | 1674 | rec_tov = get_fsp_rec_tov(fsp); |
| 1676 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, | 1675 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, |
| 1676 | fc_fcp_pkt_destroy, | ||
| 1677 | fsp, jiffies_to_msecs(rec_tov)); | 1677 | fsp, jiffies_to_msecs(rec_tov)); |
| 1678 | if (!seq) | 1678 | if (!seq) |
| 1679 | goto retry; | 1679 | goto retry; |
| @@ -1720,7 +1720,6 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
| 1720 | return; | 1720 | return; |
| 1721 | } | 1721 | } |
| 1722 | 1722 | ||
| 1723 | fsp->recov_seq = NULL; | ||
| 1724 | switch (fc_frame_payload_op(fp)) { | 1723 | switch (fc_frame_payload_op(fp)) { |
| 1725 | case ELS_LS_ACC: | 1724 | case ELS_LS_ACC: |
| 1726 | fsp->recov_retry = 0; | 1725 | fsp->recov_retry = 0; |
| @@ -1732,10 +1731,9 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
| 1732 | break; | 1731 | break; |
| 1733 | } | 1732 | } |
| 1734 | fc_fcp_unlock_pkt(fsp); | 1733 | fc_fcp_unlock_pkt(fsp); |
| 1735 | fsp->lp->tt.exch_done(seq); | ||
| 1736 | out: | 1734 | out: |
| 1735 | fsp->lp->tt.exch_done(seq); | ||
| 1737 | fc_frame_free(fp); | 1736 | fc_frame_free(fp); |
| 1738 | fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ | ||
| 1739 | } | 1737 | } |
| 1740 | 1738 | ||
| 1741 | /** | 1739 | /** |
| @@ -1747,8 +1745,6 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
| 1747 | { | 1745 | { |
| 1748 | if (fc_fcp_lock_pkt(fsp)) | 1746 | if (fc_fcp_lock_pkt(fsp)) |
| 1749 | goto out; | 1747 | goto out; |
| 1750 | fsp->lp->tt.exch_done(fsp->recov_seq); | ||
| 1751 | fsp->recov_seq = NULL; | ||
| 1752 | switch (PTR_ERR(fp)) { | 1748 | switch (PTR_ERR(fp)) { |
| 1753 | case -FC_EX_TIMEOUT: | 1749 | case -FC_EX_TIMEOUT: |
| 1754 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) | 1750 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) |
| @@ -1764,7 +1760,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) | |||
| 1764 | } | 1760 | } |
| 1765 | fc_fcp_unlock_pkt(fsp); | 1761 | fc_fcp_unlock_pkt(fsp); |
| 1766 | out: | 1762 | out: |
| 1767 | fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */ | 1763 | fsp->lp->tt.exch_done(fsp->recov_seq); |
| 1768 | } | 1764 | } |
| 1769 | 1765 | ||
| 1770 | /** | 1766 | /** |
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index fedc819d70c0..c7d071289af5 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h | |||
| @@ -108,6 +108,7 @@ extern struct fc4_prov fc_rport_fcp_init; /* FCP initiator provider */ | |||
| 108 | * Set up direct-data placement for this I/O request | 108 | * Set up direct-data placement for this I/O request |
| 109 | */ | 109 | */ |
| 110 | void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); | 110 | void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid); |
| 111 | void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp); | ||
| 111 | 112 | ||
| 112 | /* | 113 | /* |
| 113 | * Module setup functions | 114 | * Module setup functions |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 31fc21f4d831..db9238f2ecb8 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
| @@ -99,19 +99,29 @@ static void sas_ata_task_done(struct sas_task *task) | |||
| 99 | struct sas_ha_struct *sas_ha; | 99 | struct sas_ha_struct *sas_ha; |
| 100 | enum ata_completion_errors ac; | 100 | enum ata_completion_errors ac; |
| 101 | unsigned long flags; | 101 | unsigned long flags; |
| 102 | struct ata_link *link; | ||
| 102 | 103 | ||
| 103 | if (!qc) | 104 | if (!qc) |
| 104 | goto qc_already_gone; | 105 | goto qc_already_gone; |
| 105 | 106 | ||
| 106 | dev = qc->ap->private_data; | 107 | dev = qc->ap->private_data; |
| 107 | sas_ha = dev->port->ha; | 108 | sas_ha = dev->port->ha; |
| 109 | link = &dev->sata_dev.ap->link; | ||
| 108 | 110 | ||
| 109 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | 111 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); |
| 110 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || | 112 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || |
| 111 | ((stat->stat == SAM_STAT_CHECK_CONDITION && | 113 | ((stat->stat == SAM_STAT_CHECK_CONDITION && |
| 112 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { | 114 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { |
| 113 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); | 115 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); |
| 114 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | 116 | |
| 117 | if (!link->sactive) { | ||
| 118 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
| 119 | } else { | ||
| 120 | link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
| 121 | if (unlikely(link->eh_info.err_mask)) | ||
| 122 | qc->flags |= ATA_QCFLAG_FAILED; | ||
| 123 | } | ||
| 124 | |||
| 115 | dev->sata_dev.sstatus = resp->sstatus; | 125 | dev->sata_dev.sstatus = resp->sstatus; |
| 116 | dev->sata_dev.serror = resp->serror; | 126 | dev->sata_dev.serror = resp->serror; |
| 117 | dev->sata_dev.scontrol = resp->scontrol; | 127 | dev->sata_dev.scontrol = resp->scontrol; |
| @@ -121,7 +131,13 @@ static void sas_ata_task_done(struct sas_task *task) | |||
| 121 | SAS_DPRINTK("%s: SAS error %x\n", __func__, | 131 | SAS_DPRINTK("%s: SAS error %x\n", __func__, |
| 122 | stat->stat); | 132 | stat->stat); |
| 123 | /* We saw a SAS error. Send a vague error. */ | 133 | /* We saw a SAS error. Send a vague error. */ |
| 124 | qc->err_mask = ac; | 134 | if (!link->sactive) { |
| 135 | qc->err_mask = ac; | ||
| 136 | } else { | ||
| 137 | link->eh_info.err_mask |= AC_ERR_DEV; | ||
| 138 | qc->flags |= ATA_QCFLAG_FAILED; | ||
| 139 | } | ||
| 140 | |||
| 125 | dev->sata_dev.tf.feature = 0x04; /* status err */ | 141 | dev->sata_dev.tf.feature = 0x04; /* status err */ |
| 126 | dev->sata_dev.tf.command = ATA_ERR; | 142 | dev->sata_dev.tf.command = ATA_ERR; |
| 127 | } | 143 | } |
| @@ -279,6 +295,44 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, | |||
| 279 | return ret; | 295 | return ret; |
| 280 | } | 296 | } |
| 281 | 297 | ||
| 298 | static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class, | ||
| 299 | unsigned long deadline) | ||
| 300 | { | ||
| 301 | struct ata_port *ap = link->ap; | ||
| 302 | struct domain_device *dev = ap->private_data; | ||
| 303 | struct sas_internal *i = | ||
| 304 | to_sas_internal(dev->port->ha->core.shost->transportt); | ||
| 305 | int res = TMF_RESP_FUNC_FAILED; | ||
| 306 | int ret = 0; | ||
| 307 | |||
| 308 | if (i->dft->lldd_ata_soft_reset) | ||
| 309 | res = i->dft->lldd_ata_soft_reset(dev); | ||
| 310 | |||
| 311 | if (res != TMF_RESP_FUNC_COMPLETE) { | ||
| 312 | SAS_DPRINTK("%s: Unable to soft reset\n", __func__); | ||
| 313 | ret = -EAGAIN; | ||
| 314 | } | ||
| 315 | |||
| 316 | switch (dev->sata_dev.command_set) { | ||
| 317 | case ATA_COMMAND_SET: | ||
| 318 | SAS_DPRINTK("%s: Found ATA device.\n", __func__); | ||
| 319 | *class = ATA_DEV_ATA; | ||
| 320 | break; | ||
| 321 | case ATAPI_COMMAND_SET: | ||
| 322 | SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); | ||
| 323 | *class = ATA_DEV_ATAPI; | ||
| 324 | break; | ||
| 325 | default: | ||
| 326 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", | ||
| 327 | __func__, dev->sata_dev.command_set); | ||
| 328 | *class = ATA_DEV_UNKNOWN; | ||
| 329 | break; | ||
| 330 | } | ||
| 331 | |||
| 332 | ap->cbl = ATA_CBL_SATA; | ||
| 333 | return ret; | ||
| 334 | } | ||
| 335 | |||
| 282 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | 336 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) |
| 283 | { | 337 | { |
| 284 | if (qc->flags & ATA_QCFLAG_FAILED) | 338 | if (qc->flags & ATA_QCFLAG_FAILED) |
| @@ -309,7 +363,7 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) | |||
| 309 | 363 | ||
| 310 | static struct ata_port_operations sas_sata_ops = { | 364 | static struct ata_port_operations sas_sata_ops = { |
| 311 | .prereset = ata_std_prereset, | 365 | .prereset = ata_std_prereset, |
| 312 | .softreset = NULL, | 366 | .softreset = sas_ata_soft_reset, |
| 313 | .hardreset = sas_ata_hard_reset, | 367 | .hardreset = sas_ata_hard_reset, |
| 314 | .postreset = ata_std_postreset, | 368 | .postreset = ata_std_postreset, |
| 315 | .error_handler = ata_std_error_handler, | 369 | .error_handler = ata_std_error_handler, |
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 8b538bd1ff2b..14e21b5fb8ba 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h | |||
| @@ -57,7 +57,7 @@ int sas_init_queue(struct sas_ha_struct *sas_ha); | |||
| 57 | int sas_init_events(struct sas_ha_struct *sas_ha); | 57 | int sas_init_events(struct sas_ha_struct *sas_ha); |
| 58 | void sas_shutdown_queue(struct sas_ha_struct *sas_ha); | 58 | void sas_shutdown_queue(struct sas_ha_struct *sas_ha); |
| 59 | 59 | ||
| 60 | void sas_deform_port(struct asd_sas_phy *phy); | 60 | void sas_deform_port(struct asd_sas_phy *phy, int gone); |
| 61 | 61 | ||
| 62 | void sas_porte_bytes_dmaed(struct work_struct *work); | 62 | void sas_porte_bytes_dmaed(struct work_struct *work); |
| 63 | void sas_porte_broadcast_rcvd(struct work_struct *work); | 63 | void sas_porte_broadcast_rcvd(struct work_struct *work); |
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c index b459c4b635b1..e0f5018e9071 100644 --- a/drivers/scsi/libsas/sas_phy.c +++ b/drivers/scsi/libsas/sas_phy.c | |||
| @@ -39,7 +39,7 @@ static void sas_phye_loss_of_signal(struct work_struct *work) | |||
| 39 | sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, | 39 | sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, |
| 40 | &phy->phy_events_pending); | 40 | &phy->phy_events_pending); |
| 41 | phy->error = 0; | 41 | phy->error = 0; |
| 42 | sas_deform_port(phy); | 42 | sas_deform_port(phy, 1); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static void sas_phye_oob_done(struct work_struct *work) | 45 | static void sas_phye_oob_done(struct work_struct *work) |
| @@ -66,7 +66,7 @@ static void sas_phye_oob_error(struct work_struct *work) | |||
| 66 | sas_begin_event(PHYE_OOB_ERROR, &phy->ha->event_lock, | 66 | sas_begin_event(PHYE_OOB_ERROR, &phy->ha->event_lock, |
| 67 | &phy->phy_events_pending); | 67 | &phy->phy_events_pending); |
| 68 | 68 | ||
| 69 | sas_deform_port(phy); | 69 | sas_deform_port(phy, 1); |
| 70 | 70 | ||
| 71 | if (!port && phy->enabled && i->dft->lldd_control_phy) { | 71 | if (!port && phy->enabled && i->dft->lldd_control_phy) { |
| 72 | phy->error++; | 72 | phy->error++; |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 5257fdfe699a..42fd1f25b664 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
| @@ -57,7 +57,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
| 57 | 57 | ||
| 58 | if (port) { | 58 | if (port) { |
| 59 | if (!phy_is_wideport_member(port, phy)) | 59 | if (!phy_is_wideport_member(port, phy)) |
| 60 | sas_deform_port(phy); | 60 | sas_deform_port(phy, 0); |
| 61 | else { | 61 | else { |
| 62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", | 62 | SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", |
| 63 | __func__, phy->id, phy->port->id, | 63 | __func__, phy->id, phy->port->id, |
| @@ -153,28 +153,31 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
| 153 | * This is called when the physical link to the other phy has been | 153 | * This is called when the physical link to the other phy has been |
| 154 | * lost (on this phy), in Event thread context. We cannot delay here. | 154 | * lost (on this phy), in Event thread context. We cannot delay here. |
| 155 | */ | 155 | */ |
| 156 | void sas_deform_port(struct asd_sas_phy *phy) | 156 | void sas_deform_port(struct asd_sas_phy *phy, int gone) |
| 157 | { | 157 | { |
| 158 | struct sas_ha_struct *sas_ha = phy->ha; | 158 | struct sas_ha_struct *sas_ha = phy->ha; |
| 159 | struct asd_sas_port *port = phy->port; | 159 | struct asd_sas_port *port = phy->port; |
| 160 | struct sas_internal *si = | 160 | struct sas_internal *si = |
| 161 | to_sas_internal(sas_ha->core.shost->transportt); | 161 | to_sas_internal(sas_ha->core.shost->transportt); |
| 162 | struct domain_device *dev; | ||
| 162 | unsigned long flags; | 163 | unsigned long flags; |
| 163 | 164 | ||
| 164 | if (!port) | 165 | if (!port) |
| 165 | return; /* done by a phy event */ | 166 | return; /* done by a phy event */ |
| 166 | 167 | ||
| 167 | if (port->port_dev) | 168 | dev = port->port_dev; |
| 168 | port->port_dev->pathways--; | 169 | if (dev) |
| 170 | dev->pathways--; | ||
| 169 | 171 | ||
| 170 | if (port->num_phys == 1) { | 172 | if (port->num_phys == 1) { |
| 173 | if (dev && gone) | ||
| 174 | dev->gone = 1; | ||
| 171 | sas_unregister_domain_devices(port); | 175 | sas_unregister_domain_devices(port); |
| 172 | sas_port_delete(port->port); | 176 | sas_port_delete(port->port); |
| 173 | port->port = NULL; | 177 | port->port = NULL; |
| 174 | } else | 178 | } else |
| 175 | sas_port_delete_phy(port->port, phy->phy); | 179 | sas_port_delete_phy(port->port, phy->phy); |
| 176 | 180 | ||
| 177 | |||
| 178 | if (si->dft->lldd_port_deformed) | 181 | if (si->dft->lldd_port_deformed) |
| 179 | si->dft->lldd_port_deformed(phy); | 182 | si->dft->lldd_port_deformed(phy); |
| 180 | 183 | ||
| @@ -244,7 +247,7 @@ void sas_porte_link_reset_err(struct work_struct *work) | |||
| 244 | sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, | 247 | sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, |
| 245 | &phy->port_events_pending); | 248 | &phy->port_events_pending); |
| 246 | 249 | ||
| 247 | sas_deform_port(phy); | 250 | sas_deform_port(phy, 1); |
| 248 | } | 251 | } |
| 249 | 252 | ||
| 250 | void sas_porte_timer_event(struct work_struct *work) | 253 | void sas_porte_timer_event(struct work_struct *work) |
| @@ -256,7 +259,7 @@ void sas_porte_timer_event(struct work_struct *work) | |||
| 256 | sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, | 259 | sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, |
| 257 | &phy->port_events_pending); | 260 | &phy->port_events_pending); |
| 258 | 261 | ||
| 259 | sas_deform_port(phy); | 262 | sas_deform_port(phy, 1); |
| 260 | } | 263 | } |
| 261 | 264 | ||
| 262 | void sas_porte_hard_reset(struct work_struct *work) | 265 | void sas_porte_hard_reset(struct work_struct *work) |
| @@ -268,7 +271,7 @@ void sas_porte_hard_reset(struct work_struct *work) | |||
| 268 | sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, | 271 | sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, |
| 269 | &phy->port_events_pending); | 272 | &phy->port_events_pending); |
| 270 | 273 | ||
| 271 | sas_deform_port(phy); | 274 | sas_deform_port(phy, 1); |
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | /* ---------- SAS port registration ---------- */ | 277 | /* ---------- SAS port registration ---------- */ |
| @@ -306,6 +309,6 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha) | |||
| 306 | 309 | ||
| 307 | for (i = 0; i < sas_ha->num_phys; i++) | 310 | for (i = 0; i < sas_ha->num_phys; i++) |
| 308 | if (sas_ha->sas_phy[i]->port) | 311 | if (sas_ha->sas_phy[i]->port) |
| 309 | sas_deform_port(sas_ha->sas_phy[i]); | 312 | sas_deform_port(sas_ha->sas_phy[i], 0); |
| 310 | 313 | ||
| 311 | } | 314 | } |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f6e189f40917..eeba76cdf774 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
| @@ -207,6 +207,13 @@ static int sas_queuecommand_lck(struct scsi_cmnd *cmd, | |||
| 207 | struct sas_ha_struct *sas_ha = dev->port->ha; | 207 | struct sas_ha_struct *sas_ha = dev->port->ha; |
| 208 | struct sas_task *task; | 208 | struct sas_task *task; |
| 209 | 209 | ||
| 210 | /* If the device fell off, no sense in issuing commands */ | ||
| 211 | if (dev->gone) { | ||
| 212 | cmd->result = DID_BAD_TARGET << 16; | ||
| 213 | scsi_done(cmd); | ||
| 214 | goto out; | ||
| 215 | } | ||
| 216 | |||
| 210 | if (dev_is_sata(dev)) { | 217 | if (dev_is_sata(dev)) { |
| 211 | unsigned long flags; | 218 | unsigned long flags; |
| 212 | 219 | ||
| @@ -216,13 +223,6 @@ static int sas_queuecommand_lck(struct scsi_cmnd *cmd, | |||
| 216 | goto out; | 223 | goto out; |
| 217 | } | 224 | } |
| 218 | 225 | ||
| 219 | /* If the device fell off, no sense in issuing commands */ | ||
| 220 | if (dev->gone) { | ||
| 221 | cmd->result = DID_BAD_TARGET << 16; | ||
| 222 | scsi_done(cmd); | ||
| 223 | goto out; | ||
| 224 | } | ||
| 225 | |||
| 226 | res = -ENOMEM; | 226 | res = -ENOMEM; |
| 227 | task = sas_create_task(cmd, dev, GFP_ATOMIC); | 227 | task = sas_create_task(cmd, dev, GFP_ATOMIC); |
| 228 | if (!task) | 228 | if (!task) |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 02d53d89534f..8ec2c86a49d4 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -41,6 +41,7 @@ struct lpfc_sli2_slim; | |||
| 41 | downloads using bsg */ | 41 | downloads using bsg */ |
| 42 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ | 42 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ |
| 43 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ | 43 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ |
| 44 | #define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */ | ||
| 44 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ | 45 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ |
| 45 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ | 46 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ |
| 46 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ | 47 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ |
| @@ -486,6 +487,42 @@ struct unsol_rcv_ct_ctx { | |||
| 486 | (1 << LPFC_USER_LINK_SPEED_AUTO)) | 487 | (1 << LPFC_USER_LINK_SPEED_AUTO)) |
| 487 | #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" | 488 | #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" |
| 488 | 489 | ||
| 490 | enum nemb_type { | ||
| 491 | nemb_mse = 1, | ||
| 492 | nemb_hbd | ||
| 493 | }; | ||
| 494 | |||
| 495 | enum mbox_type { | ||
| 496 | mbox_rd = 1, | ||
| 497 | mbox_wr | ||
| 498 | }; | ||
| 499 | |||
| 500 | enum dma_type { | ||
| 501 | dma_mbox = 1, | ||
| 502 | dma_ebuf | ||
| 503 | }; | ||
| 504 | |||
| 505 | enum sta_type { | ||
| 506 | sta_pre_addr = 1, | ||
| 507 | sta_pos_addr | ||
| 508 | }; | ||
| 509 | |||
| 510 | struct lpfc_mbox_ext_buf_ctx { | ||
| 511 | uint32_t state; | ||
| 512 | #define LPFC_BSG_MBOX_IDLE 0 | ||
| 513 | #define LPFC_BSG_MBOX_HOST 1 | ||
| 514 | #define LPFC_BSG_MBOX_PORT 2 | ||
| 515 | #define LPFC_BSG_MBOX_DONE 3 | ||
| 516 | #define LPFC_BSG_MBOX_ABTS 4 | ||
| 517 | enum nemb_type nembType; | ||
| 518 | enum mbox_type mboxType; | ||
| 519 | uint32_t numBuf; | ||
| 520 | uint32_t mbxTag; | ||
| 521 | uint32_t seqNum; | ||
| 522 | struct lpfc_dmabuf *mbx_dmabuf; | ||
| 523 | struct list_head ext_dmabuf_list; | ||
| 524 | }; | ||
| 525 | |||
| 489 | struct lpfc_hba { | 526 | struct lpfc_hba { |
| 490 | /* SCSI interface function jump table entries */ | 527 | /* SCSI interface function jump table entries */ |
| 491 | int (*lpfc_new_scsi_buf) | 528 | int (*lpfc_new_scsi_buf) |
| @@ -589,6 +626,7 @@ struct lpfc_hba { | |||
| 589 | 626 | ||
| 590 | MAILBOX_t *mbox; | 627 | MAILBOX_t *mbox; |
| 591 | uint32_t *mbox_ext; | 628 | uint32_t *mbox_ext; |
| 629 | struct lpfc_mbox_ext_buf_ctx mbox_ext_buf_ctx; | ||
| 592 | uint32_t ha_copy; | 630 | uint32_t ha_copy; |
| 593 | struct _PCB *pcb; | 631 | struct _PCB *pcb; |
| 594 | struct _IOCB *IOCBs; | 632 | struct _IOCB *IOCBs; |
| @@ -659,6 +697,7 @@ struct lpfc_hba { | |||
| 659 | uint32_t cfg_hostmem_hgp; | 697 | uint32_t cfg_hostmem_hgp; |
| 660 | uint32_t cfg_log_verbose; | 698 | uint32_t cfg_log_verbose; |
| 661 | uint32_t cfg_aer_support; | 699 | uint32_t cfg_aer_support; |
| 700 | uint32_t cfg_sriov_nr_virtfn; | ||
| 662 | uint32_t cfg_iocb_cnt; | 701 | uint32_t cfg_iocb_cnt; |
| 663 | uint32_t cfg_suppress_link_up; | 702 | uint32_t cfg_suppress_link_up; |
| 664 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ | 703 | #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ |
| @@ -706,7 +745,6 @@ struct lpfc_hba { | |||
| 706 | uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */ | 745 | uint32_t *hbq_get; /* Host mem address of HBQ get ptrs */ |
| 707 | 746 | ||
| 708 | int brd_no; /* FC board number */ | 747 | int brd_no; /* FC board number */ |
| 709 | |||
| 710 | char SerialNumber[32]; /* adapter Serial Number */ | 748 | char SerialNumber[32]; /* adapter Serial Number */ |
| 711 | char OptionROMVersion[32]; /* adapter BIOS / Fcode version */ | 749 | char OptionROMVersion[32]; /* adapter BIOS / Fcode version */ |
| 712 | char ModelDesc[256]; /* Model Description */ | 750 | char ModelDesc[256]; /* Model Description */ |
| @@ -778,6 +816,9 @@ struct lpfc_hba { | |||
| 778 | uint16_t vpi_base; | 816 | uint16_t vpi_base; |
| 779 | uint16_t vfi_base; | 817 | uint16_t vfi_base; |
| 780 | unsigned long *vpi_bmask; /* vpi allocation table */ | 818 | unsigned long *vpi_bmask; /* vpi allocation table */ |
| 819 | uint16_t *vpi_ids; | ||
| 820 | uint16_t vpi_count; | ||
| 821 | struct list_head lpfc_vpi_blk_list; | ||
| 781 | 822 | ||
| 782 | /* Data structure used by fabric iocb scheduler */ | 823 | /* Data structure used by fabric iocb scheduler */ |
| 783 | struct list_head fabric_iocb_list; | 824 | struct list_head fabric_iocb_list; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 8dcbf8fff673..135a53baa735 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -755,6 +755,73 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, | |||
| 755 | } | 755 | } |
| 756 | 756 | ||
| 757 | /** | 757 | /** |
| 758 | * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc | ||
| 759 | * @phba: lpfc_hba pointer. | ||
| 760 | * | ||
| 761 | * Description: | ||
| 762 | * Request SLI4 interface type-2 device to perform a physical register set | ||
| 763 | * access. | ||
| 764 | * | ||
| 765 | * Returns: | ||
| 766 | * zero for success | ||
| 767 | **/ | ||
| 768 | static ssize_t | ||
| 769 | lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) | ||
| 770 | { | ||
| 771 | struct completion online_compl; | ||
| 772 | uint32_t reg_val; | ||
| 773 | int status = 0; | ||
| 774 | int rc; | ||
| 775 | |||
| 776 | if (!phba->cfg_enable_hba_reset) | ||
| 777 | return -EIO; | ||
| 778 | |||
| 779 | if ((phba->sli_rev < LPFC_SLI_REV4) || | ||
| 780 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 781 | LPFC_SLI_INTF_IF_TYPE_2)) | ||
| 782 | return -EPERM; | ||
| 783 | |||
| 784 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | ||
| 785 | |||
| 786 | if (status != 0) | ||
| 787 | return status; | ||
| 788 | |||
| 789 | /* wait for the device to be quiesced before firmware reset */ | ||
| 790 | msleep(100); | ||
| 791 | |||
| 792 | reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + | ||
| 793 | LPFC_CTL_PDEV_CTL_OFFSET); | ||
| 794 | |||
| 795 | if (opcode == LPFC_FW_DUMP) | ||
| 796 | reg_val |= LPFC_FW_DUMP_REQUEST; | ||
| 797 | else if (opcode == LPFC_FW_RESET) | ||
| 798 | reg_val |= LPFC_CTL_PDEV_CTL_FRST; | ||
| 799 | else if (opcode == LPFC_DV_RESET) | ||
| 800 | reg_val |= LPFC_CTL_PDEV_CTL_DRST; | ||
| 801 | |||
| 802 | writel(reg_val, phba->sli4_hba.conf_regs_memmap_p + | ||
| 803 | LPFC_CTL_PDEV_CTL_OFFSET); | ||
| 804 | /* flush */ | ||
| 805 | readl(phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET); | ||
| 806 | |||
| 807 | /* delay driver action following IF_TYPE_2 reset */ | ||
| 808 | msleep(100); | ||
| 809 | |||
| 810 | init_completion(&online_compl); | ||
| 811 | rc = lpfc_workq_post_event(phba, &status, &online_compl, | ||
| 812 | LPFC_EVT_ONLINE); | ||
| 813 | if (rc == 0) | ||
| 814 | return -ENOMEM; | ||
| 815 | |||
| 816 | wait_for_completion(&online_compl); | ||
| 817 | |||
| 818 | if (status != 0) | ||
| 819 | return -EIO; | ||
| 820 | |||
| 821 | return 0; | ||
| 822 | } | ||
| 823 | |||
| 824 | /** | ||
| 758 | * lpfc_nport_evt_cnt_show - Return the number of nport events | 825 | * lpfc_nport_evt_cnt_show - Return the number of nport events |
| 759 | * @dev: class device that is converted into a Scsi_host. | 826 | * @dev: class device that is converted into a Scsi_host. |
| 760 | * @attr: device attribute, not used. | 827 | * @attr: device attribute, not used. |
| @@ -848,6 +915,12 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, | |||
| 848 | return -EINVAL; | 915 | return -EINVAL; |
| 849 | else | 916 | else |
| 850 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); | 917 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); |
| 918 | else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) | ||
| 919 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_DUMP); | ||
| 920 | else if (strncmp(buf, "fw_reset", sizeof("fw_reset") - 1) == 0) | ||
| 921 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_FW_RESET); | ||
| 922 | else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) | ||
| 923 | status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET); | ||
| 851 | else | 924 | else |
| 852 | return -EINVAL; | 925 | return -EINVAL; |
| 853 | 926 | ||
| @@ -1322,6 +1395,102 @@ lpfc_dss_show(struct device *dev, struct device_attribute *attr, | |||
| 1322 | } | 1395 | } |
| 1323 | 1396 | ||
| 1324 | /** | 1397 | /** |
| 1398 | * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions | ||
| 1399 | * @dev: class converted to a Scsi_host structure. | ||
| 1400 | * @attr: device attribute, not used. | ||
| 1401 | * @buf: on return contains the formatted support level. | ||
| 1402 | * | ||
| 1403 | * Description: | ||
| 1404 | * Returns the maximum number of virtual functions a physical function can | ||
| 1405 | * support, 0 will be returned if called on virtual function. | ||
| 1406 | * | ||
| 1407 | * Returns: size of formatted string. | ||
| 1408 | **/ | ||
| 1409 | static ssize_t | ||
| 1410 | lpfc_sriov_hw_max_virtfn_show(struct device *dev, | ||
| 1411 | struct device_attribute *attr, | ||
| 1412 | char *buf) | ||
| 1413 | { | ||
| 1414 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 1415 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
| 1416 | struct lpfc_hba *phba = vport->phba; | ||
| 1417 | struct pci_dev *pdev = phba->pcidev; | ||
| 1418 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 1419 | uint32_t shdr_status, shdr_add_status; | ||
| 1420 | LPFC_MBOXQ_t *mboxq; | ||
| 1421 | struct lpfc_mbx_get_prof_cfg *get_prof_cfg; | ||
| 1422 | struct lpfc_rsrc_desc_pcie *desc; | ||
| 1423 | uint32_t max_nr_virtfn; | ||
| 1424 | uint32_t desc_count; | ||
| 1425 | int length, rc, i; | ||
| 1426 | |||
| 1427 | if ((phba->sli_rev < LPFC_SLI_REV4) || | ||
| 1428 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 1429 | LPFC_SLI_INTF_IF_TYPE_2)) | ||
| 1430 | return -EPERM; | ||
| 1431 | |||
| 1432 | if (!pdev->is_physfn) | ||
| 1433 | return snprintf(buf, PAGE_SIZE, "%d\n", 0); | ||
| 1434 | |||
| 1435 | mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 1436 | if (!mboxq) | ||
| 1437 | return -ENOMEM; | ||
| 1438 | |||
| 1439 | /* get the maximum number of virtfn support by physfn */ | ||
| 1440 | length = (sizeof(struct lpfc_mbx_get_prof_cfg) - | ||
| 1441 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 1442 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 1443 | LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG, | ||
| 1444 | length, LPFC_SLI4_MBX_EMBED); | ||
| 1445 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
| 1446 | &mboxq->u.mqe.un.sli4_config.header.cfg_shdr; | ||
| 1447 | bf_set(lpfc_mbox_hdr_pf_num, &shdr->request, | ||
| 1448 | phba->sli4_hba.iov.pf_number + 1); | ||
| 1449 | |||
| 1450 | get_prof_cfg = &mboxq->u.mqe.un.get_prof_cfg; | ||
| 1451 | bf_set(lpfc_mbx_get_prof_cfg_prof_tp, &get_prof_cfg->u.request, | ||
| 1452 | LPFC_CFG_TYPE_CURRENT_ACTIVE); | ||
| 1453 | |||
| 1454 | rc = lpfc_sli_issue_mbox_wait(phba, mboxq, | ||
| 1455 | lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG)); | ||
| 1456 | |||
| 1457 | if (rc != MBX_TIMEOUT) { | ||
| 1458 | /* check return status */ | ||
| 1459 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 1460 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
| 1461 | &shdr->response); | ||
| 1462 | if (shdr_status || shdr_add_status || rc) | ||
| 1463 | goto error_out; | ||
| 1464 | |||
| 1465 | } else | ||
| 1466 | goto error_out; | ||
| 1467 | |||
| 1468 | desc_count = get_prof_cfg->u.response.prof_cfg.rsrc_desc_count; | ||
| 1469 | |||
| 1470 | for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) { | ||
| 1471 | desc = (struct lpfc_rsrc_desc_pcie *) | ||
| 1472 | &get_prof_cfg->u.response.prof_cfg.desc[i]; | ||
| 1473 | if (LPFC_RSRC_DESC_TYPE_PCIE == | ||
| 1474 | bf_get(lpfc_rsrc_desc_pcie_type, desc)) { | ||
| 1475 | max_nr_virtfn = bf_get(lpfc_rsrc_desc_pcie_nr_virtfn, | ||
| 1476 | desc); | ||
| 1477 | break; | ||
| 1478 | } | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | if (i < LPFC_RSRC_DESC_MAX_NUM) { | ||
| 1482 | if (rc != MBX_TIMEOUT) | ||
| 1483 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
| 1484 | return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn); | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | error_out: | ||
| 1488 | if (rc != MBX_TIMEOUT) | ||
| 1489 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
| 1490 | return -EIO; | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | /** | ||
| 1325 | * lpfc_param_show - Return a cfg attribute value in decimal | 1494 | * lpfc_param_show - Return a cfg attribute value in decimal |
| 1326 | * | 1495 | * |
| 1327 | * Description: | 1496 | * Description: |
| @@ -1762,6 +1931,8 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); | |||
| 1762 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); | 1931 | static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); |
| 1763 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); | 1932 | static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); |
| 1764 | static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); | 1933 | static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); |
| 1934 | static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, | ||
| 1935 | lpfc_sriov_hw_max_virtfn_show, NULL); | ||
| 1765 | 1936 | ||
| 1766 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; | 1937 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
| 1767 | 1938 | ||
| @@ -3014,7 +3185,7 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, | |||
| 3014 | * | 3185 | * |
| 3015 | * @dev: class device that is converted into a Scsi_host. | 3186 | * @dev: class device that is converted into a Scsi_host. |
| 3016 | * @attr: device attribute, not used. | 3187 | * @attr: device attribute, not used. |
| 3017 | * @buf: containing the string "selective". | 3188 | * @buf: containing enable or disable aer flag. |
| 3018 | * @count: unused variable. | 3189 | * @count: unused variable. |
| 3019 | * | 3190 | * |
| 3020 | * Description: | 3191 | * Description: |
| @@ -3098,7 +3269,7 @@ lpfc_param_show(aer_support) | |||
| 3098 | /** | 3269 | /** |
| 3099 | * lpfc_aer_support_init - Set the initial adapters aer support flag | 3270 | * lpfc_aer_support_init - Set the initial adapters aer support flag |
| 3100 | * @phba: lpfc_hba pointer. | 3271 | * @phba: lpfc_hba pointer. |
| 3101 | * @val: link speed value. | 3272 | * @val: enable aer or disable aer flag. |
| 3102 | * | 3273 | * |
| 3103 | * Description: | 3274 | * Description: |
| 3104 | * If val is in a valid range [0,1], then set the adapter's initial | 3275 | * If val is in a valid range [0,1], then set the adapter's initial |
| @@ -3137,7 +3308,7 @@ static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR, | |||
| 3137 | * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device | 3308 | * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device |
| 3138 | * @dev: class device that is converted into a Scsi_host. | 3309 | * @dev: class device that is converted into a Scsi_host. |
| 3139 | * @attr: device attribute, not used. | 3310 | * @attr: device attribute, not used. |
| 3140 | * @buf: containing the string "selective". | 3311 | * @buf: containing flag 1 for aer cleanup state. |
| 3141 | * @count: unused variable. | 3312 | * @count: unused variable. |
| 3142 | * | 3313 | * |
| 3143 | * Description: | 3314 | * Description: |
| @@ -3180,6 +3351,136 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, | |||
| 3180 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, | 3351 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, |
| 3181 | lpfc_aer_cleanup_state); | 3352 | lpfc_aer_cleanup_state); |
| 3182 | 3353 | ||
| 3354 | /** | ||
| 3355 | * lpfc_sriov_nr_virtfn_store - Enable the adapter for sr-iov virtual functions | ||
| 3356 | * | ||
| 3357 | * @dev: class device that is converted into a Scsi_host. | ||
| 3358 | * @attr: device attribute, not used. | ||
| 3359 | * @buf: containing the string the number of vfs to be enabled. | ||
| 3360 | * @count: unused variable. | ||
| 3361 | * | ||
| 3362 | * Description: | ||
| 3363 | * When this api is called either through user sysfs, the driver shall | ||
| 3364 | * try to enable or disable SR-IOV virtual functions according to the | ||
| 3365 | * following: | ||
| 3366 | * | ||
| 3367 | * If zero virtual function has been enabled to the physical function, | ||
| 3368 | * the driver shall invoke the pci enable virtual function api trying | ||
| 3369 | * to enable the virtual functions. If the nr_vfn provided is greater | ||
| 3370 | * than the maximum supported, the maximum virtual function number will | ||
| 3371 | * be used for invoking the api; otherwise, the nr_vfn provided shall | ||
| 3372 | * be used for invoking the api. If the api call returned success, the | ||
| 3373 | * actual number of virtual functions enabled will be set to the driver | ||
| 3374 | * cfg_sriov_nr_virtfn; otherwise, -EINVAL shall be returned and driver | ||
| 3375 | * cfg_sriov_nr_virtfn remains zero. | ||
| 3376 | * | ||
| 3377 | * If none-zero virtual functions have already been enabled to the | ||
| 3378 | * physical function, as reflected by the driver's cfg_sriov_nr_virtfn, | ||
| 3379 | * -EINVAL will be returned and the driver does nothing; | ||
| 3380 | * | ||
| 3381 | * If the nr_vfn provided is zero and none-zero virtual functions have | ||
| 3382 | * been enabled, as indicated by the driver's cfg_sriov_nr_virtfn, the | ||
| 3383 | * disabling virtual function api shall be invoded to disable all the | ||
| 3384 | * virtual functions and driver's cfg_sriov_nr_virtfn shall be set to | ||
| 3385 | * zero. Otherwise, if zero virtual function has been enabled, do | ||
| 3386 | * nothing. | ||
| 3387 | * | ||
| 3388 | * Returns: | ||
| 3389 | * length of the buf on success if val is in range the intended mode | ||
| 3390 | * is supported. | ||
| 3391 | * -EINVAL if val out of range or intended mode is not supported. | ||
| 3392 | **/ | ||
| 3393 | static ssize_t | ||
| 3394 | lpfc_sriov_nr_virtfn_store(struct device *dev, struct device_attribute *attr, | ||
| 3395 | const char *buf, size_t count) | ||
| 3396 | { | ||
| 3397 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 3398 | struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; | ||
| 3399 | struct lpfc_hba *phba = vport->phba; | ||
| 3400 | struct pci_dev *pdev = phba->pcidev; | ||
| 3401 | int val = 0, rc = -EINVAL; | ||
| 3402 | |||
| 3403 | /* Sanity check on user data */ | ||
| 3404 | if (!isdigit(buf[0])) | ||
| 3405 | return -EINVAL; | ||
| 3406 | if (sscanf(buf, "%i", &val) != 1) | ||
| 3407 | return -EINVAL; | ||
| 3408 | if (val < 0) | ||
| 3409 | return -EINVAL; | ||
| 3410 | |||
| 3411 | /* Request disabling virtual functions */ | ||
| 3412 | if (val == 0) { | ||
| 3413 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
| 3414 | pci_disable_sriov(pdev); | ||
| 3415 | phba->cfg_sriov_nr_virtfn = 0; | ||
| 3416 | } | ||
| 3417 | return strlen(buf); | ||
| 3418 | } | ||
| 3419 | |||
| 3420 | /* Request enabling virtual functions */ | ||
| 3421 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
| 3422 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 3423 | "3018 There are %d virtual functions " | ||
| 3424 | "enabled on physical function.\n", | ||
| 3425 | phba->cfg_sriov_nr_virtfn); | ||
| 3426 | return -EEXIST; | ||
| 3427 | } | ||
| 3428 | |||
| 3429 | if (val <= LPFC_MAX_VFN_PER_PFN) | ||
| 3430 | phba->cfg_sriov_nr_virtfn = val; | ||
| 3431 | else { | ||
| 3432 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 3433 | "3019 Enabling %d virtual functions is not " | ||
| 3434 | "allowed.\n", val); | ||
| 3435 | return -EINVAL; | ||
| 3436 | } | ||
| 3437 | |||
| 3438 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, phba->cfg_sriov_nr_virtfn); | ||
| 3439 | if (rc) { | ||
| 3440 | phba->cfg_sriov_nr_virtfn = 0; | ||
| 3441 | rc = -EPERM; | ||
| 3442 | } else | ||
| 3443 | rc = strlen(buf); | ||
| 3444 | |||
| 3445 | return rc; | ||
| 3446 | } | ||
| 3447 | |||
| 3448 | static int lpfc_sriov_nr_virtfn = LPFC_DEF_VFN_PER_PFN; | ||
| 3449 | module_param(lpfc_sriov_nr_virtfn, int, S_IRUGO|S_IWUSR); | ||
| 3450 | MODULE_PARM_DESC(lpfc_sriov_nr_virtfn, "Enable PCIe device SR-IOV virtual fn"); | ||
| 3451 | lpfc_param_show(sriov_nr_virtfn) | ||
| 3452 | |||
| 3453 | /** | ||
| 3454 | * lpfc_sriov_nr_virtfn_init - Set the initial sr-iov virtual function enable | ||
| 3455 | * @phba: lpfc_hba pointer. | ||
| 3456 | * @val: link speed value. | ||
| 3457 | * | ||
| 3458 | * Description: | ||
| 3459 | * If val is in a valid range [0,255], then set the adapter's initial | ||
| 3460 | * cfg_sriov_nr_virtfn field. If it's greater than the maximum, the maximum | ||
| 3461 | * number shall be used instead. It will be up to the driver's probe_one | ||
| 3462 | * routine to determine whether the device's SR-IOV is supported or not. | ||
| 3463 | * | ||
| 3464 | * Returns: | ||
| 3465 | * zero if val saved. | ||
| 3466 | * -EINVAL val out of range | ||
| 3467 | **/ | ||
| 3468 | static int | ||
| 3469 | lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val) | ||
| 3470 | { | ||
| 3471 | if (val >= 0 && val <= LPFC_MAX_VFN_PER_PFN) { | ||
| 3472 | phba->cfg_sriov_nr_virtfn = val; | ||
| 3473 | return 0; | ||
| 3474 | } | ||
| 3475 | |||
| 3476 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 3477 | "3017 Enabling %d virtual functions is not " | ||
| 3478 | "allowed.\n", val); | ||
| 3479 | return -EINVAL; | ||
| 3480 | } | ||
| 3481 | static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR, | ||
| 3482 | lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store); | ||
| 3483 | |||
| 3183 | /* | 3484 | /* |
| 3184 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. | 3485 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. |
| 3185 | # Value range is [2,3]. Default value is 3. | 3486 | # Value range is [2,3]. Default value is 3. |
| @@ -3497,6 +3798,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
| 3497 | &dev_attr_lpfc_prot_sg_seg_cnt, | 3798 | &dev_attr_lpfc_prot_sg_seg_cnt, |
| 3498 | &dev_attr_lpfc_aer_support, | 3799 | &dev_attr_lpfc_aer_support, |
| 3499 | &dev_attr_lpfc_aer_state_cleanup, | 3800 | &dev_attr_lpfc_aer_state_cleanup, |
| 3801 | &dev_attr_lpfc_sriov_nr_virtfn, | ||
| 3500 | &dev_attr_lpfc_suppress_link_up, | 3802 | &dev_attr_lpfc_suppress_link_up, |
| 3501 | &dev_attr_lpfc_iocb_cnt, | 3803 | &dev_attr_lpfc_iocb_cnt, |
| 3502 | &dev_attr_iocb_hw, | 3804 | &dev_attr_iocb_hw, |
| @@ -3505,6 +3807,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
| 3505 | &dev_attr_lpfc_fips_level, | 3807 | &dev_attr_lpfc_fips_level, |
| 3506 | &dev_attr_lpfc_fips_rev, | 3808 | &dev_attr_lpfc_fips_rev, |
| 3507 | &dev_attr_lpfc_dss, | 3809 | &dev_attr_lpfc_dss, |
| 3810 | &dev_attr_lpfc_sriov_hw_max_virtfn, | ||
| 3508 | NULL, | 3811 | NULL, |
| 3509 | }; | 3812 | }; |
| 3510 | 3813 | ||
| @@ -3961,7 +4264,7 @@ static struct bin_attribute sysfs_mbox_attr = { | |||
| 3961 | .name = "mbox", | 4264 | .name = "mbox", |
| 3962 | .mode = S_IRUSR | S_IWUSR, | 4265 | .mode = S_IRUSR | S_IWUSR, |
| 3963 | }, | 4266 | }, |
| 3964 | .size = MAILBOX_CMD_SIZE, | 4267 | .size = MAILBOX_SYSFS_MAX, |
| 3965 | .read = sysfs_mbox_read, | 4268 | .read = sysfs_mbox_read, |
| 3966 | .write = sysfs_mbox_write, | 4269 | .write = sysfs_mbox_write, |
| 3967 | }; | 4270 | }; |
| @@ -4705,6 +5008,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
| 4705 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); | 5008 | lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); |
| 4706 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); | 5009 | lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); |
| 4707 | lpfc_aer_support_init(phba, lpfc_aer_support); | 5010 | lpfc_aer_support_init(phba, lpfc_aer_support); |
| 5011 | lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn); | ||
| 4708 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); | 5012 | lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); |
| 4709 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); | 5013 | lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); |
| 4710 | phba->cfg_enable_dss = 1; | 5014 | phba->cfg_enable_dss = 1; |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 853e5042f39c..7fb0ba4cbfa7 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/list.h> | ||
| 26 | 27 | ||
| 27 | #include <scsi/scsi.h> | 28 | #include <scsi/scsi.h> |
| 28 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
| @@ -79,8 +80,7 @@ struct lpfc_bsg_iocb { | |||
| 79 | struct lpfc_bsg_mbox { | 80 | struct lpfc_bsg_mbox { |
| 80 | LPFC_MBOXQ_t *pmboxq; | 81 | LPFC_MBOXQ_t *pmboxq; |
| 81 | MAILBOX_t *mb; | 82 | MAILBOX_t *mb; |
| 82 | struct lpfc_dmabuf *rxbmp; /* for BIU diags */ | 83 | struct lpfc_dmabuf *dmabuffers; /* for BIU diags */ |
| 83 | struct lpfc_dmabufext *dmp; /* for BIU diags */ | ||
| 84 | uint8_t *ext; /* extended mailbox data */ | 84 | uint8_t *ext; /* extended mailbox data */ |
| 85 | uint32_t mbOffset; /* from app */ | 85 | uint32_t mbOffset; /* from app */ |
| 86 | uint32_t inExtWLen; /* from app */ | 86 | uint32_t inExtWLen; /* from app */ |
| @@ -332,6 +332,8 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
| 332 | cmd->ulpLe = 1; | 332 | cmd->ulpLe = 1; |
| 333 | cmd->ulpClass = CLASS3; | 333 | cmd->ulpClass = CLASS3; |
| 334 | cmd->ulpContext = ndlp->nlp_rpi; | 334 | cmd->ulpContext = ndlp->nlp_rpi; |
| 335 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 336 | cmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
| 335 | cmd->ulpOwner = OWN_CHIP; | 337 | cmd->ulpOwner = OWN_CHIP; |
| 336 | cmdiocbq->vport = phba->pport; | 338 | cmdiocbq->vport = phba->pport; |
| 337 | cmdiocbq->context3 = bmp; | 339 | cmdiocbq->context3 = bmp; |
| @@ -1336,6 +1338,10 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
| 1336 | } | 1338 | } |
| 1337 | 1339 | ||
| 1338 | icmd->un.ulpWord[3] = ndlp->nlp_rpi; | 1340 | icmd->un.ulpWord[3] = ndlp->nlp_rpi; |
| 1341 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 1342 | icmd->ulpContext = | ||
| 1343 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
| 1344 | |||
| 1339 | /* The exchange is done, mark the entry as invalid */ | 1345 | /* The exchange is done, mark the entry as invalid */ |
| 1340 | phba->ct_ctx[tag].flags &= ~UNSOL_VALID; | 1346 | phba->ct_ctx[tag].flags &= ~UNSOL_VALID; |
| 1341 | } else | 1347 | } else |
| @@ -1463,11 +1469,91 @@ send_mgmt_rsp_exit: | |||
| 1463 | } | 1469 | } |
| 1464 | 1470 | ||
| 1465 | /** | 1471 | /** |
| 1466 | * lpfc_bsg_diag_mode - process a LPFC_BSG_VENDOR_DIAG_MODE bsg vendor command | 1472 | * lpfc_bsg_diag_mode_enter - process preparing into device diag loopback mode |
| 1473 | * @phba: Pointer to HBA context object. | ||
| 1467 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | 1474 | * @job: LPFC_BSG_VENDOR_DIAG_MODE |
| 1468 | * | 1475 | * |
| 1469 | * This function is responsible for placing a port into diagnostic loopback | 1476 | * This function is responsible for preparing driver for diag loopback |
| 1470 | * mode in order to perform a diagnostic loopback test. | 1477 | * on device. |
| 1478 | */ | ||
| 1479 | static int | ||
| 1480 | lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
| 1481 | { | ||
| 1482 | struct lpfc_vport **vports; | ||
| 1483 | struct Scsi_Host *shost; | ||
| 1484 | struct lpfc_sli *psli; | ||
| 1485 | struct lpfc_sli_ring *pring; | ||
| 1486 | int i = 0; | ||
| 1487 | |||
| 1488 | psli = &phba->sli; | ||
| 1489 | if (!psli) | ||
| 1490 | return -ENODEV; | ||
| 1491 | |||
| 1492 | pring = &psli->ring[LPFC_FCP_RING]; | ||
| 1493 | if (!pring) | ||
| 1494 | return -ENODEV; | ||
| 1495 | |||
| 1496 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
| 1497 | (psli->sli_flag & LPFC_BLOCK_MGMT_IO) || | ||
| 1498 | (!(psli->sli_flag & LPFC_SLI_ACTIVE))) | ||
| 1499 | return -EACCES; | ||
| 1500 | |||
| 1501 | vports = lpfc_create_vport_work_array(phba); | ||
| 1502 | if (vports) { | ||
| 1503 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
| 1504 | shost = lpfc_shost_from_vport(vports[i]); | ||
| 1505 | scsi_block_requests(shost); | ||
| 1506 | } | ||
| 1507 | lpfc_destroy_vport_work_array(phba, vports); | ||
| 1508 | } else { | ||
| 1509 | shost = lpfc_shost_from_vport(phba->pport); | ||
| 1510 | scsi_block_requests(shost); | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | while (pring->txcmplq_cnt) { | ||
| 1514 | if (i++ > 500) /* wait up to 5 seconds */ | ||
| 1515 | break; | ||
| 1516 | msleep(10); | ||
| 1517 | } | ||
| 1518 | return 0; | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | /** | ||
| 1522 | * lpfc_bsg_diag_mode_exit - exit process from device diag loopback mode | ||
| 1523 | * @phba: Pointer to HBA context object. | ||
| 1524 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
| 1525 | * | ||
| 1526 | * This function is responsible for driver exit processing of setting up | ||
| 1527 | * diag loopback mode on device. | ||
| 1528 | */ | ||
| 1529 | static void | ||
| 1530 | lpfc_bsg_diag_mode_exit(struct lpfc_hba *phba) | ||
| 1531 | { | ||
| 1532 | struct Scsi_Host *shost; | ||
| 1533 | struct lpfc_vport **vports; | ||
| 1534 | int i; | ||
| 1535 | |||
| 1536 | vports = lpfc_create_vport_work_array(phba); | ||
| 1537 | if (vports) { | ||
| 1538 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
| 1539 | shost = lpfc_shost_from_vport(vports[i]); | ||
| 1540 | scsi_unblock_requests(shost); | ||
| 1541 | } | ||
| 1542 | lpfc_destroy_vport_work_array(phba, vports); | ||
| 1543 | } else { | ||
| 1544 | shost = lpfc_shost_from_vport(phba->pport); | ||
| 1545 | scsi_unblock_requests(shost); | ||
| 1546 | } | ||
| 1547 | return; | ||
| 1548 | } | ||
| 1549 | |||
| 1550 | /** | ||
| 1551 | * lpfc_sli3_bsg_diag_loopback_mode - process an sli3 bsg vendor command | ||
| 1552 | * @phba: Pointer to HBA context object. | ||
| 1553 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
| 1554 | * | ||
| 1555 | * This function is responsible for placing an sli3 port into diagnostic | ||
| 1556 | * loopback mode in order to perform a diagnostic loopback test. | ||
| 1471 | * All new scsi requests are blocked, a small delay is used to allow the | 1557 | * All new scsi requests are blocked, a small delay is used to allow the |
| 1472 | * scsi requests to complete then the link is brought down. If the link is | 1558 | * scsi requests to complete then the link is brought down. If the link is |
| 1473 | * is placed in loopback mode then scsi requests are again allowed | 1559 | * is placed in loopback mode then scsi requests are again allowed |
| @@ -1475,17 +1561,11 @@ send_mgmt_rsp_exit: | |||
| 1475 | * All of this is done in-line. | 1561 | * All of this is done in-line. |
| 1476 | */ | 1562 | */ |
| 1477 | static int | 1563 | static int |
| 1478 | lpfc_bsg_diag_mode(struct fc_bsg_job *job) | 1564 | lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) |
| 1479 | { | 1565 | { |
| 1480 | struct Scsi_Host *shost = job->shost; | ||
| 1481 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | ||
| 1482 | struct lpfc_hba *phba = vport->phba; | ||
| 1483 | struct diag_mode_set *loopback_mode; | 1566 | struct diag_mode_set *loopback_mode; |
| 1484 | struct lpfc_sli *psli = &phba->sli; | ||
| 1485 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_FCP_RING]; | ||
| 1486 | uint32_t link_flags; | 1567 | uint32_t link_flags; |
| 1487 | uint32_t timeout; | 1568 | uint32_t timeout; |
| 1488 | struct lpfc_vport **vports; | ||
| 1489 | LPFC_MBOXQ_t *pmboxq; | 1569 | LPFC_MBOXQ_t *pmboxq; |
| 1490 | int mbxstatus; | 1570 | int mbxstatus; |
| 1491 | int i = 0; | 1571 | int i = 0; |
| @@ -1494,53 +1574,33 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job) | |||
| 1494 | /* no data to return just the return code */ | 1574 | /* no data to return just the return code */ |
| 1495 | job->reply->reply_payload_rcv_len = 0; | 1575 | job->reply->reply_payload_rcv_len = 0; |
| 1496 | 1576 | ||
| 1497 | if (job->request_len < | 1577 | if (job->request_len < sizeof(struct fc_bsg_request) + |
| 1498 | sizeof(struct fc_bsg_request) + sizeof(struct diag_mode_set)) { | 1578 | sizeof(struct diag_mode_set)) { |
| 1499 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | 1579 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, |
| 1500 | "2738 Received DIAG MODE request below minimum " | 1580 | "2738 Received DIAG MODE request size:%d " |
| 1501 | "size\n"); | 1581 | "below the minimum size:%d\n", |
| 1582 | job->request_len, | ||
| 1583 | (int)(sizeof(struct fc_bsg_request) + | ||
| 1584 | sizeof(struct diag_mode_set))); | ||
| 1502 | rc = -EINVAL; | 1585 | rc = -EINVAL; |
| 1503 | goto job_error; | 1586 | goto job_error; |
| 1504 | } | 1587 | } |
| 1505 | 1588 | ||
| 1589 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
| 1590 | if (rc) | ||
| 1591 | goto job_error; | ||
| 1592 | |||
| 1593 | /* bring the link to diagnostic mode */ | ||
| 1506 | loopback_mode = (struct diag_mode_set *) | 1594 | loopback_mode = (struct diag_mode_set *) |
| 1507 | job->request->rqst_data.h_vendor.vendor_cmd; | 1595 | job->request->rqst_data.h_vendor.vendor_cmd; |
| 1508 | link_flags = loopback_mode->type; | 1596 | link_flags = loopback_mode->type; |
| 1509 | timeout = loopback_mode->timeout * 100; | 1597 | timeout = loopback_mode->timeout * 100; |
| 1510 | 1598 | ||
| 1511 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
| 1512 | (psli->sli_flag & LPFC_BLOCK_MGMT_IO) || | ||
| 1513 | (!(psli->sli_flag & LPFC_SLI_ACTIVE))) { | ||
| 1514 | rc = -EACCES; | ||
| 1515 | goto job_error; | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 1599 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 1519 | if (!pmboxq) { | 1600 | if (!pmboxq) { |
| 1520 | rc = -ENOMEM; | 1601 | rc = -ENOMEM; |
| 1521 | goto job_error; | 1602 | goto loopback_mode_exit; |
| 1522 | } | ||
| 1523 | |||
| 1524 | vports = lpfc_create_vport_work_array(phba); | ||
| 1525 | if (vports) { | ||
| 1526 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
| 1527 | shost = lpfc_shost_from_vport(vports[i]); | ||
| 1528 | scsi_block_requests(shost); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | lpfc_destroy_vport_work_array(phba, vports); | ||
| 1532 | } else { | ||
| 1533 | shost = lpfc_shost_from_vport(phba->pport); | ||
| 1534 | scsi_block_requests(shost); | ||
| 1535 | } | 1603 | } |
| 1536 | |||
| 1537 | while (pring->txcmplq_cnt) { | ||
| 1538 | if (i++ > 500) /* wait up to 5 seconds */ | ||
| 1539 | break; | ||
| 1540 | |||
| 1541 | msleep(10); | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | 1604 | memset((void *)pmboxq, 0, sizeof(LPFC_MBOXQ_t)); |
| 1545 | pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; | 1605 | pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; |
| 1546 | pmboxq->u.mb.mbxOwner = OWN_HOST; | 1606 | pmboxq->u.mb.mbxOwner = OWN_HOST; |
| @@ -1594,22 +1654,186 @@ lpfc_bsg_diag_mode(struct fc_bsg_job *job) | |||
| 1594 | rc = -ENODEV; | 1654 | rc = -ENODEV; |
| 1595 | 1655 | ||
| 1596 | loopback_mode_exit: | 1656 | loopback_mode_exit: |
| 1597 | vports = lpfc_create_vport_work_array(phba); | 1657 | lpfc_bsg_diag_mode_exit(phba); |
| 1598 | if (vports) { | 1658 | |
| 1599 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 1659 | /* |
| 1600 | shost = lpfc_shost_from_vport(vports[i]); | 1660 | * Let SLI layer release mboxq if mbox command completed after timeout. |
| 1601 | scsi_unblock_requests(shost); | 1661 | */ |
| 1662 | if (mbxstatus != MBX_TIMEOUT) | ||
| 1663 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 1664 | |||
| 1665 | job_error: | ||
| 1666 | /* make error code available to userspace */ | ||
| 1667 | job->reply->result = rc; | ||
| 1668 | /* complete the job back to userspace if no error */ | ||
| 1669 | if (rc == 0) | ||
| 1670 | job->job_done(job); | ||
| 1671 | return rc; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | /** | ||
| 1675 | * lpfc_sli4_bsg_set_link_diag_state - set sli4 link diag state | ||
| 1676 | * @phba: Pointer to HBA context object. | ||
| 1677 | * @diag: Flag for set link to diag or nomral operation state. | ||
| 1678 | * | ||
| 1679 | * This function is responsible for issuing a sli4 mailbox command for setting | ||
| 1680 | * link to either diag state or normal operation state. | ||
| 1681 | */ | ||
| 1682 | static int | ||
| 1683 | lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag) | ||
| 1684 | { | ||
| 1685 | LPFC_MBOXQ_t *pmboxq; | ||
| 1686 | struct lpfc_mbx_set_link_diag_state *link_diag_state; | ||
| 1687 | uint32_t req_len, alloc_len; | ||
| 1688 | int mbxstatus = MBX_SUCCESS, rc; | ||
| 1689 | |||
| 1690 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 1691 | if (!pmboxq) | ||
| 1692 | return -ENOMEM; | ||
| 1693 | |||
| 1694 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) - | ||
| 1695 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 1696 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
| 1697 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE, | ||
| 1698 | req_len, LPFC_SLI4_MBX_EMBED); | ||
| 1699 | if (alloc_len != req_len) { | ||
| 1700 | rc = -ENOMEM; | ||
| 1701 | goto link_diag_state_set_out; | ||
| 1702 | } | ||
| 1703 | link_diag_state = &pmboxq->u.mqe.un.link_diag_state; | ||
| 1704 | bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req, | ||
| 1705 | phba->sli4_hba.link_state.number); | ||
| 1706 | bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req, | ||
| 1707 | phba->sli4_hba.link_state.type); | ||
| 1708 | if (diag) | ||
| 1709 | bf_set(lpfc_mbx_set_diag_state_diag, | ||
| 1710 | &link_diag_state->u.req, 1); | ||
| 1711 | else | ||
| 1712 | bf_set(lpfc_mbx_set_diag_state_diag, | ||
| 1713 | &link_diag_state->u.req, 0); | ||
| 1714 | |||
| 1715 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | ||
| 1716 | |||
| 1717 | if ((mbxstatus == MBX_SUCCESS) && (pmboxq->u.mb.mbxStatus == 0)) | ||
| 1718 | rc = 0; | ||
| 1719 | else | ||
| 1720 | rc = -ENODEV; | ||
| 1721 | |||
| 1722 | link_diag_state_set_out: | ||
| 1723 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) | ||
| 1724 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 1725 | |||
| 1726 | return rc; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | /** | ||
| 1730 | * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command | ||
| 1731 | * @phba: Pointer to HBA context object. | ||
| 1732 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
| 1733 | * | ||
| 1734 | * This function is responsible for placing an sli4 port into diagnostic | ||
| 1735 | * loopback mode in order to perform a diagnostic loopback test. | ||
| 1736 | */ | ||
| 1737 | static int | ||
| 1738 | lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
| 1739 | { | ||
| 1740 | struct diag_mode_set *loopback_mode; | ||
| 1741 | uint32_t link_flags, timeout, req_len, alloc_len; | ||
| 1742 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; | ||
| 1743 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
| 1744 | int mbxstatus, i, rc = 0; | ||
| 1745 | |||
| 1746 | /* no data to return just the return code */ | ||
| 1747 | job->reply->reply_payload_rcv_len = 0; | ||
| 1748 | |||
| 1749 | if (job->request_len < sizeof(struct fc_bsg_request) + | ||
| 1750 | sizeof(struct diag_mode_set)) { | ||
| 1751 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 1752 | "3011 Received DIAG MODE request size:%d " | ||
| 1753 | "below the minimum size:%d\n", | ||
| 1754 | job->request_len, | ||
| 1755 | (int)(sizeof(struct fc_bsg_request) + | ||
| 1756 | sizeof(struct diag_mode_set))); | ||
| 1757 | rc = -EINVAL; | ||
| 1758 | goto job_error; | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
| 1762 | if (rc) | ||
| 1763 | goto job_error; | ||
| 1764 | |||
| 1765 | /* bring the link to diagnostic mode */ | ||
| 1766 | loopback_mode = (struct diag_mode_set *) | ||
| 1767 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 1768 | link_flags = loopback_mode->type; | ||
| 1769 | timeout = loopback_mode->timeout * 100; | ||
| 1770 | |||
| 1771 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); | ||
| 1772 | if (rc) | ||
| 1773 | goto loopback_mode_exit; | ||
| 1774 | |||
| 1775 | /* wait for link down before proceeding */ | ||
| 1776 | i = 0; | ||
| 1777 | while (phba->link_state != LPFC_LINK_DOWN) { | ||
| 1778 | if (i++ > timeout) { | ||
| 1779 | rc = -ETIMEDOUT; | ||
| 1780 | goto loopback_mode_exit; | ||
| 1781 | } | ||
| 1782 | msleep(10); | ||
| 1783 | } | ||
| 1784 | /* set up loopback mode */ | ||
| 1785 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 1786 | if (!pmboxq) { | ||
| 1787 | rc = -ENOMEM; | ||
| 1788 | goto loopback_mode_exit; | ||
| 1789 | } | ||
| 1790 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - | ||
| 1791 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 1792 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
| 1793 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, | ||
| 1794 | req_len, LPFC_SLI4_MBX_EMBED); | ||
| 1795 | if (alloc_len != req_len) { | ||
| 1796 | rc = -ENOMEM; | ||
| 1797 | goto loopback_mode_exit; | ||
| 1798 | } | ||
| 1799 | link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; | ||
| 1800 | bf_set(lpfc_mbx_set_diag_state_link_num, | ||
| 1801 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.number); | ||
| 1802 | bf_set(lpfc_mbx_set_diag_state_link_type, | ||
| 1803 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.type); | ||
| 1804 | if (link_flags == INTERNAL_LOOP_BACK) | ||
| 1805 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
| 1806 | &link_diag_loopback->u.req, | ||
| 1807 | LPFC_DIAG_LOOPBACK_TYPE_INTERNAL); | ||
| 1808 | else | ||
| 1809 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
| 1810 | &link_diag_loopback->u.req, | ||
| 1811 | LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL); | ||
| 1812 | |||
| 1813 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | ||
| 1814 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) | ||
| 1815 | rc = -ENODEV; | ||
| 1816 | else { | ||
| 1817 | phba->link_flag |= LS_LOOPBACK_MODE; | ||
| 1818 | /* wait for the link attention interrupt */ | ||
| 1819 | msleep(100); | ||
| 1820 | i = 0; | ||
| 1821 | while (phba->link_state != LPFC_HBA_READY) { | ||
| 1822 | if (i++ > timeout) { | ||
| 1823 | rc = -ETIMEDOUT; | ||
| 1824 | break; | ||
| 1825 | } | ||
| 1826 | msleep(10); | ||
| 1602 | } | 1827 | } |
| 1603 | lpfc_destroy_vport_work_array(phba, vports); | ||
| 1604 | } else { | ||
| 1605 | shost = lpfc_shost_from_vport(phba->pport); | ||
| 1606 | scsi_unblock_requests(shost); | ||
| 1607 | } | 1828 | } |
| 1608 | 1829 | ||
| 1830 | loopback_mode_exit: | ||
| 1831 | lpfc_bsg_diag_mode_exit(phba); | ||
| 1832 | |||
| 1609 | /* | 1833 | /* |
| 1610 | * Let SLI layer release mboxq if mbox command completed after timeout. | 1834 | * Let SLI layer release mboxq if mbox command completed after timeout. |
| 1611 | */ | 1835 | */ |
| 1612 | if (mbxstatus != MBX_TIMEOUT) | 1836 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) |
| 1613 | mempool_free(pmboxq, phba->mbox_mem_pool); | 1837 | mempool_free(pmboxq, phba->mbox_mem_pool); |
| 1614 | 1838 | ||
| 1615 | job_error: | 1839 | job_error: |
| @@ -1622,6 +1846,234 @@ job_error: | |||
| 1622 | } | 1846 | } |
| 1623 | 1847 | ||
| 1624 | /** | 1848 | /** |
| 1849 | * lpfc_bsg_diag_loopback_mode - bsg vendor command for diag loopback mode | ||
| 1850 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | ||
| 1851 | * | ||
| 1852 | * This function is responsible for responding to check and dispatch bsg diag | ||
| 1853 | * command from the user to proper driver action routines. | ||
| 1854 | */ | ||
| 1855 | static int | ||
| 1856 | lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) | ||
| 1857 | { | ||
| 1858 | struct Scsi_Host *shost; | ||
| 1859 | struct lpfc_vport *vport; | ||
| 1860 | struct lpfc_hba *phba; | ||
| 1861 | int rc; | ||
| 1862 | |||
| 1863 | shost = job->shost; | ||
| 1864 | if (!shost) | ||
| 1865 | return -ENODEV; | ||
| 1866 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
| 1867 | if (!vport) | ||
| 1868 | return -ENODEV; | ||
| 1869 | phba = vport->phba; | ||
| 1870 | if (!phba) | ||
| 1871 | return -ENODEV; | ||
| 1872 | |||
| 1873 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
| 1874 | rc = lpfc_sli3_bsg_diag_loopback_mode(phba, job); | ||
| 1875 | else if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == | ||
| 1876 | LPFC_SLI_INTF_IF_TYPE_2) | ||
| 1877 | rc = lpfc_sli4_bsg_diag_loopback_mode(phba, job); | ||
| 1878 | else | ||
| 1879 | rc = -ENODEV; | ||
| 1880 | |||
| 1881 | return rc; | ||
| 1882 | |||
| 1883 | } | ||
| 1884 | |||
| 1885 | /** | ||
| 1886 | * lpfc_sli4_bsg_diag_mode_end - sli4 bsg vendor command for ending diag mode | ||
| 1887 | * @job: LPFC_BSG_VENDOR_DIAG_MODE_END | ||
| 1888 | * | ||
| 1889 | * This function is responsible for responding to check and dispatch bsg diag | ||
| 1890 | * command from the user to proper driver action routines. | ||
| 1891 | */ | ||
| 1892 | static int | ||
| 1893 | lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) | ||
| 1894 | { | ||
| 1895 | struct Scsi_Host *shost; | ||
| 1896 | struct lpfc_vport *vport; | ||
| 1897 | struct lpfc_hba *phba; | ||
| 1898 | int rc; | ||
| 1899 | |||
| 1900 | shost = job->shost; | ||
| 1901 | if (!shost) | ||
| 1902 | return -ENODEV; | ||
| 1903 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
| 1904 | if (!vport) | ||
| 1905 | return -ENODEV; | ||
| 1906 | phba = vport->phba; | ||
| 1907 | if (!phba) | ||
| 1908 | return -ENODEV; | ||
| 1909 | |||
| 1910 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
| 1911 | return -ENODEV; | ||
| 1912 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 1913 | LPFC_SLI_INTF_IF_TYPE_2) | ||
| 1914 | return -ENODEV; | ||
| 1915 | |||
| 1916 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); | ||
| 1917 | |||
| 1918 | if (!rc) | ||
| 1919 | rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); | ||
| 1920 | |||
| 1921 | return rc; | ||
| 1922 | } | ||
| 1923 | |||
| 1924 | /** | ||
| 1925 | * lpfc_sli4_bsg_link_diag_test - sli4 bsg vendor command for diag link test | ||
| 1926 | * @job: LPFC_BSG_VENDOR_DIAG_LINK_TEST | ||
| 1927 | * | ||
| 1928 | * This function is to perform SLI4 diag link test request from the user | ||
| 1929 | * applicaiton. | ||
| 1930 | */ | ||
| 1931 | static int | ||
| 1932 | lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) | ||
| 1933 | { | ||
| 1934 | struct Scsi_Host *shost; | ||
| 1935 | struct lpfc_vport *vport; | ||
| 1936 | struct lpfc_hba *phba; | ||
| 1937 | LPFC_MBOXQ_t *pmboxq; | ||
| 1938 | struct sli4_link_diag *link_diag_test_cmd; | ||
| 1939 | uint32_t req_len, alloc_len; | ||
| 1940 | uint32_t timeout; | ||
| 1941 | struct lpfc_mbx_run_link_diag_test *run_link_diag_test; | ||
| 1942 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 1943 | uint32_t shdr_status, shdr_add_status; | ||
| 1944 | struct diag_status *diag_status_reply; | ||
| 1945 | int mbxstatus, rc = 0; | ||
| 1946 | |||
| 1947 | shost = job->shost; | ||
| 1948 | if (!shost) { | ||
| 1949 | rc = -ENODEV; | ||
| 1950 | goto job_error; | ||
| 1951 | } | ||
| 1952 | vport = (struct lpfc_vport *)job->shost->hostdata; | ||
| 1953 | if (!vport) { | ||
| 1954 | rc = -ENODEV; | ||
| 1955 | goto job_error; | ||
| 1956 | } | ||
| 1957 | phba = vport->phba; | ||
| 1958 | if (!phba) { | ||
| 1959 | rc = -ENODEV; | ||
| 1960 | goto job_error; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | if (phba->sli_rev < LPFC_SLI_REV4) { | ||
| 1964 | rc = -ENODEV; | ||
| 1965 | goto job_error; | ||
| 1966 | } | ||
| 1967 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 1968 | LPFC_SLI_INTF_IF_TYPE_2) { | ||
| 1969 | rc = -ENODEV; | ||
| 1970 | goto job_error; | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | if (job->request_len < sizeof(struct fc_bsg_request) + | ||
| 1974 | sizeof(struct sli4_link_diag)) { | ||
| 1975 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 1976 | "3013 Received LINK DIAG TEST request " | ||
| 1977 | " size:%d below the minimum size:%d\n", | ||
| 1978 | job->request_len, | ||
| 1979 | (int)(sizeof(struct fc_bsg_request) + | ||
| 1980 | sizeof(struct sli4_link_diag))); | ||
| 1981 | rc = -EINVAL; | ||
| 1982 | goto job_error; | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | rc = lpfc_bsg_diag_mode_enter(phba, job); | ||
| 1986 | if (rc) | ||
| 1987 | goto job_error; | ||
| 1988 | |||
| 1989 | link_diag_test_cmd = (struct sli4_link_diag *) | ||
| 1990 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 1991 | timeout = link_diag_test_cmd->timeout * 100; | ||
| 1992 | |||
| 1993 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); | ||
| 1994 | |||
| 1995 | if (rc) | ||
| 1996 | goto job_error; | ||
| 1997 | |||
| 1998 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 1999 | if (!pmboxq) { | ||
| 2000 | rc = -ENOMEM; | ||
| 2001 | goto link_diag_test_exit; | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_state) - | ||
| 2005 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 2006 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
| 2007 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE, | ||
| 2008 | req_len, LPFC_SLI4_MBX_EMBED); | ||
| 2009 | if (alloc_len != req_len) { | ||
| 2010 | rc = -ENOMEM; | ||
| 2011 | goto link_diag_test_exit; | ||
| 2012 | } | ||
| 2013 | run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; | ||
| 2014 | bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, | ||
| 2015 | phba->sli4_hba.link_state.number); | ||
| 2016 | bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req, | ||
| 2017 | phba->sli4_hba.link_state.type); | ||
| 2018 | bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req, | ||
| 2019 | link_diag_test_cmd->test_id); | ||
| 2020 | bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req, | ||
| 2021 | link_diag_test_cmd->loops); | ||
| 2022 | bf_set(lpfc_mbx_run_diag_test_test_ver, &run_link_diag_test->u.req, | ||
| 2023 | link_diag_test_cmd->test_version); | ||
| 2024 | bf_set(lpfc_mbx_run_diag_test_err_act, &run_link_diag_test->u.req, | ||
| 2025 | link_diag_test_cmd->error_action); | ||
| 2026 | |||
| 2027 | mbxstatus = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); | ||
| 2028 | |||
| 2029 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
| 2030 | &pmboxq->u.mqe.un.sli4_config.header.cfg_shdr; | ||
| 2031 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 2032 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
| 2033 | if (shdr_status || shdr_add_status || mbxstatus) { | ||
| 2034 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 2035 | "3010 Run link diag test mailbox failed with " | ||
| 2036 | "mbx_status x%x status x%x, add_status x%x\n", | ||
| 2037 | mbxstatus, shdr_status, shdr_add_status); | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | diag_status_reply = (struct diag_status *) | ||
| 2041 | job->reply->reply_data.vendor_reply.vendor_rsp; | ||
| 2042 | |||
| 2043 | if (job->reply_len < | ||
| 2044 | sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) { | ||
| 2045 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
| 2046 | "3012 Received Run link diag test reply " | ||
| 2047 | "below minimum size (%d): reply_len:%d\n", | ||
| 2048 | (int)(sizeof(struct fc_bsg_request) + | ||
| 2049 | sizeof(struct diag_status)), | ||
| 2050 | job->reply_len); | ||
| 2051 | rc = -EINVAL; | ||
| 2052 | goto job_error; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | diag_status_reply->mbox_status = mbxstatus; | ||
| 2056 | diag_status_reply->shdr_status = shdr_status; | ||
| 2057 | diag_status_reply->shdr_add_status = shdr_add_status; | ||
| 2058 | |||
| 2059 | link_diag_test_exit: | ||
| 2060 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); | ||
| 2061 | |||
| 2062 | if (pmboxq) | ||
| 2063 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 2064 | |||
| 2065 | lpfc_bsg_diag_mode_exit(phba); | ||
| 2066 | |||
| 2067 | job_error: | ||
| 2068 | /* make error code available to userspace */ | ||
| 2069 | job->reply->result = rc; | ||
| 2070 | /* complete the job back to userspace if no error */ | ||
| 2071 | if (rc == 0) | ||
| 2072 | job->job_done(job); | ||
| 2073 | return rc; | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | /** | ||
| 1625 | * lpfcdiag_loop_self_reg - obtains a remote port login id | 2077 | * lpfcdiag_loop_self_reg - obtains a remote port login id |
| 1626 | * @phba: Pointer to HBA context object | 2078 | * @phba: Pointer to HBA context object |
| 1627 | * @rpi: Pointer to a remote port login id | 2079 | * @rpi: Pointer to a remote port login id |
| @@ -1851,6 +2303,86 @@ err_get_xri_exit: | |||
| 1851 | } | 2303 | } |
| 1852 | 2304 | ||
| 1853 | /** | 2305 | /** |
| 2306 | * lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers | ||
| 2307 | * @phba: Pointer to HBA context object | ||
| 2308 | * | ||
| 2309 | * This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and. | ||
| 2310 | * retruns the pointer to the buffer. | ||
| 2311 | **/ | ||
| 2312 | static struct lpfc_dmabuf * | ||
| 2313 | lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba) | ||
| 2314 | { | ||
| 2315 | struct lpfc_dmabuf *dmabuf; | ||
| 2316 | struct pci_dev *pcidev = phba->pcidev; | ||
| 2317 | |||
| 2318 | /* allocate dma buffer struct */ | ||
| 2319 | dmabuf = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
| 2320 | if (!dmabuf) | ||
| 2321 | return NULL; | ||
| 2322 | |||
| 2323 | INIT_LIST_HEAD(&dmabuf->list); | ||
| 2324 | |||
| 2325 | /* now, allocate dma buffer */ | ||
| 2326 | dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE, | ||
| 2327 | &(dmabuf->phys), GFP_KERNEL); | ||
| 2328 | |||
| 2329 | if (!dmabuf->virt) { | ||
| 2330 | kfree(dmabuf); | ||
| 2331 | return NULL; | ||
| 2332 | } | ||
| 2333 | memset((uint8_t *)dmabuf->virt, 0, BSG_MBOX_SIZE); | ||
| 2334 | |||
| 2335 | return dmabuf; | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | /** | ||
| 2339 | * lpfc_bsg_dma_page_free - free a bsg mbox page sized dma buffer | ||
| 2340 | * @phba: Pointer to HBA context object. | ||
| 2341 | * @dmabuf: Pointer to the bsg mbox page sized dma buffer descriptor. | ||
| 2342 | * | ||
| 2343 | * This routine just simply frees a dma buffer and its associated buffer | ||
| 2344 | * descriptor referred by @dmabuf. | ||
| 2345 | **/ | ||
| 2346 | static void | ||
| 2347 | lpfc_bsg_dma_page_free(struct lpfc_hba *phba, struct lpfc_dmabuf *dmabuf) | ||
| 2348 | { | ||
| 2349 | struct pci_dev *pcidev = phba->pcidev; | ||
| 2350 | |||
| 2351 | if (!dmabuf) | ||
| 2352 | return; | ||
| 2353 | |||
| 2354 | if (dmabuf->virt) | ||
| 2355 | dma_free_coherent(&pcidev->dev, BSG_MBOX_SIZE, | ||
| 2356 | dmabuf->virt, dmabuf->phys); | ||
| 2357 | kfree(dmabuf); | ||
| 2358 | return; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | /** | ||
| 2362 | * lpfc_bsg_dma_page_list_free - free a list of bsg mbox page sized dma buffers | ||
| 2363 | * @phba: Pointer to HBA context object. | ||
| 2364 | * @dmabuf_list: Pointer to a list of bsg mbox page sized dma buffer descs. | ||
| 2365 | * | ||
| 2366 | * This routine just simply frees all dma buffers and their associated buffer | ||
| 2367 | * descriptors referred by @dmabuf_list. | ||
| 2368 | **/ | ||
| 2369 | static void | ||
| 2370 | lpfc_bsg_dma_page_list_free(struct lpfc_hba *phba, | ||
| 2371 | struct list_head *dmabuf_list) | ||
| 2372 | { | ||
| 2373 | struct lpfc_dmabuf *dmabuf, *next_dmabuf; | ||
| 2374 | |||
| 2375 | if (list_empty(dmabuf_list)) | ||
| 2376 | return; | ||
| 2377 | |||
| 2378 | list_for_each_entry_safe(dmabuf, next_dmabuf, dmabuf_list, list) { | ||
| 2379 | list_del_init(&dmabuf->list); | ||
| 2380 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
| 2381 | } | ||
| 2382 | return; | ||
| 2383 | } | ||
| 2384 | |||
| 2385 | /** | ||
| 1854 | * diag_cmd_data_alloc - fills in a bde struct with dma buffers | 2386 | * diag_cmd_data_alloc - fills in a bde struct with dma buffers |
| 1855 | * @phba: Pointer to HBA context object | 2387 | * @phba: Pointer to HBA context object |
| 1856 | * @bpl: Pointer to 64 bit bde structure | 2388 | * @bpl: Pointer to 64 bit bde structure |
| @@ -2067,7 +2599,7 @@ err_post_rxbufs_exit: | |||
| 2067 | } | 2599 | } |
| 2068 | 2600 | ||
| 2069 | /** | 2601 | /** |
| 2070 | * lpfc_bsg_diag_test - with a port in loopback issues a Ct cmd to itself | 2602 | * lpfc_bsg_diag_loopback_run - run loopback on a port by issue ct cmd to itself |
| 2071 | * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job | 2603 | * @job: LPFC_BSG_VENDOR_DIAG_TEST fc_bsg_job |
| 2072 | * | 2604 | * |
| 2073 | * This function receives a user data buffer to be transmitted and received on | 2605 | * This function receives a user data buffer to be transmitted and received on |
| @@ -2086,7 +2618,7 @@ err_post_rxbufs_exit: | |||
| 2086 | * of loopback mode. | 2618 | * of loopback mode. |
| 2087 | **/ | 2619 | **/ |
| 2088 | static int | 2620 | static int |
| 2089 | lpfc_bsg_diag_test(struct fc_bsg_job *job) | 2621 | lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) |
| 2090 | { | 2622 | { |
| 2091 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | 2623 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; |
| 2092 | struct lpfc_hba *phba = vport->phba; | 2624 | struct lpfc_hba *phba = vport->phba; |
| @@ -2411,7 +2943,7 @@ job_error: | |||
| 2411 | } | 2943 | } |
| 2412 | 2944 | ||
| 2413 | /** | 2945 | /** |
| 2414 | * lpfc_bsg_wake_mbox_wait - lpfc_bsg_issue_mbox mbox completion handler | 2946 | * lpfc_bsg_issue_mbox_cmpl - lpfc_bsg_issue_mbox mbox completion handler |
| 2415 | * @phba: Pointer to HBA context object. | 2947 | * @phba: Pointer to HBA context object. |
| 2416 | * @pmboxq: Pointer to mailbox command. | 2948 | * @pmboxq: Pointer to mailbox command. |
| 2417 | * | 2949 | * |
| @@ -2422,15 +2954,13 @@ job_error: | |||
| 2422 | * of the mailbox. | 2954 | * of the mailbox. |
| 2423 | **/ | 2955 | **/ |
| 2424 | void | 2956 | void |
| 2425 | lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | 2957 | lpfc_bsg_issue_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) |
| 2426 | { | 2958 | { |
| 2427 | struct bsg_job_data *dd_data; | 2959 | struct bsg_job_data *dd_data; |
| 2428 | struct fc_bsg_job *job; | 2960 | struct fc_bsg_job *job; |
| 2429 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
| 2430 | uint32_t size; | 2961 | uint32_t size; |
| 2431 | unsigned long flags; | 2962 | unsigned long flags; |
| 2432 | uint8_t *to; | 2963 | uint8_t *pmb, *pmb_buf; |
| 2433 | uint8_t *from; | ||
| 2434 | 2964 | ||
| 2435 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | 2965 | spin_lock_irqsave(&phba->ct_ev_lock, flags); |
| 2436 | dd_data = pmboxq->context1; | 2966 | dd_data = pmboxq->context1; |
| @@ -2440,62 +2970,21 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
| 2440 | return; | 2970 | return; |
| 2441 | } | 2971 | } |
| 2442 | 2972 | ||
| 2443 | /* build the outgoing buffer to do an sg copy | 2973 | /* |
| 2444 | * the format is the response mailbox followed by any extended | 2974 | * The outgoing buffer is readily referred from the dma buffer, |
| 2445 | * mailbox data | 2975 | * just need to get header part from mailboxq structure. |
| 2446 | */ | 2976 | */ |
| 2447 | from = (uint8_t *)&pmboxq->u.mb; | 2977 | pmb = (uint8_t *)&pmboxq->u.mb; |
| 2448 | to = (uint8_t *)dd_data->context_un.mbox.mb; | 2978 | pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb; |
| 2449 | memcpy(to, from, sizeof(MAILBOX_t)); | 2979 | memcpy(pmb_buf, pmb, sizeof(MAILBOX_t)); |
| 2450 | if (pmboxq->u.mb.mbxStatus == MBX_SUCCESS) { | ||
| 2451 | /* copy the extended data if any, count is in words */ | ||
| 2452 | if (dd_data->context_un.mbox.outExtWLen) { | ||
| 2453 | from = (uint8_t *)dd_data->context_un.mbox.ext; | ||
| 2454 | to += sizeof(MAILBOX_t); | ||
| 2455 | size = dd_data->context_un.mbox.outExtWLen * | ||
| 2456 | sizeof(uint32_t); | ||
| 2457 | memcpy(to, from, size); | ||
| 2458 | } else if (pmboxq->u.mb.mbxCommand == MBX_RUN_BIU_DIAG64) { | ||
| 2459 | from = (uint8_t *)dd_data->context_un.mbox. | ||
| 2460 | dmp->dma.virt; | ||
| 2461 | to += sizeof(MAILBOX_t); | ||
| 2462 | size = dd_data->context_un.mbox.dmp->size; | ||
| 2463 | memcpy(to, from, size); | ||
| 2464 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
| 2465 | (pmboxq->u.mb.mbxCommand == MBX_DUMP_MEMORY)) { | ||
| 2466 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | ||
| 2467 | virt; | ||
| 2468 | to += sizeof(MAILBOX_t); | ||
| 2469 | size = pmboxq->u.mb.un.varWords[5]; | ||
| 2470 | memcpy(to, from, size); | ||
| 2471 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | ||
| 2472 | (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) { | ||
| 2473 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | ||
| 2474 | &pmboxq->u.mb.un.varWords[0]; | ||
| 2475 | |||
| 2476 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | ||
| 2477 | virt; | ||
| 2478 | to += sizeof(MAILBOX_t); | ||
| 2479 | size = nembed_sge->sge[0].length; | ||
| 2480 | memcpy(to, from, size); | ||
| 2481 | } else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) { | ||
| 2482 | from = (uint8_t *)dd_data->context_un. | ||
| 2483 | mbox.dmp->dma.virt; | ||
| 2484 | to += sizeof(MAILBOX_t); | ||
| 2485 | size = dd_data->context_un.mbox.dmp->size; | ||
| 2486 | memcpy(to, from, size); | ||
| 2487 | } | ||
| 2488 | } | ||
| 2489 | 2980 | ||
| 2490 | from = (uint8_t *)dd_data->context_un.mbox.mb; | ||
| 2491 | job = dd_data->context_un.mbox.set_job; | 2981 | job = dd_data->context_un.mbox.set_job; |
| 2492 | if (job) { | 2982 | if (job) { |
| 2493 | size = job->reply_payload.payload_len; | 2983 | size = job->reply_payload.payload_len; |
| 2494 | job->reply->reply_payload_rcv_len = | 2984 | job->reply->reply_payload_rcv_len = |
| 2495 | sg_copy_from_buffer(job->reply_payload.sg_list, | 2985 | sg_copy_from_buffer(job->reply_payload.sg_list, |
| 2496 | job->reply_payload.sg_cnt, | 2986 | job->reply_payload.sg_cnt, |
| 2497 | from, size); | 2987 | pmb_buf, size); |
| 2498 | job->reply->result = 0; | ||
| 2499 | /* need to hold the lock until we set job->dd_data to NULL | 2988 | /* need to hold the lock until we set job->dd_data to NULL |
| 2500 | * to hold off the timeout handler returning to the mid-layer | 2989 | * to hold off the timeout handler returning to the mid-layer |
| 2501 | * while we are still processing the job. | 2990 | * while we are still processing the job. |
| @@ -2503,28 +2992,19 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
| 2503 | job->dd_data = NULL; | 2992 | job->dd_data = NULL; |
| 2504 | dd_data->context_un.mbox.set_job = NULL; | 2993 | dd_data->context_un.mbox.set_job = NULL; |
| 2505 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 2994 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
| 2506 | job->job_done(job); | ||
| 2507 | } else { | 2995 | } else { |
| 2508 | dd_data->context_un.mbox.set_job = NULL; | 2996 | dd_data->context_un.mbox.set_job = NULL; |
| 2509 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 2997 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
| 2510 | } | 2998 | } |
| 2511 | 2999 | ||
| 2512 | kfree(dd_data->context_un.mbox.mb); | ||
| 2513 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); | 3000 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); |
| 2514 | kfree(dd_data->context_un.mbox.ext); | 3001 | lpfc_bsg_dma_page_free(phba, dd_data->context_un.mbox.dmabuffers); |
| 2515 | if (dd_data->context_un.mbox.dmp) { | ||
| 2516 | dma_free_coherent(&phba->pcidev->dev, | ||
| 2517 | dd_data->context_un.mbox.dmp->size, | ||
| 2518 | dd_data->context_un.mbox.dmp->dma.virt, | ||
| 2519 | dd_data->context_un.mbox.dmp->dma.phys); | ||
| 2520 | kfree(dd_data->context_un.mbox.dmp); | ||
| 2521 | } | ||
| 2522 | if (dd_data->context_un.mbox.rxbmp) { | ||
| 2523 | lpfc_mbuf_free(phba, dd_data->context_un.mbox.rxbmp->virt, | ||
| 2524 | dd_data->context_un.mbox.rxbmp->phys); | ||
| 2525 | kfree(dd_data->context_un.mbox.rxbmp); | ||
| 2526 | } | ||
| 2527 | kfree(dd_data); | 3002 | kfree(dd_data); |
| 3003 | |||
| 3004 | if (job) { | ||
| 3005 | job->reply->result = 0; | ||
| 3006 | job->job_done(job); | ||
| 3007 | } | ||
| 2528 | return; | 3008 | return; |
| 2529 | } | 3009 | } |
| 2530 | 3010 | ||
| @@ -2619,6 +3099,1006 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
| 2619 | } | 3099 | } |
| 2620 | 3100 | ||
| 2621 | /** | 3101 | /** |
| 3102 | * lpfc_bsg_mbox_ext_cleanup - clean up context of multi-buffer mbox session | ||
| 3103 | * @phba: Pointer to HBA context object. | ||
| 3104 | * | ||
| 3105 | * This is routine clean up and reset BSG handling of multi-buffer mbox | ||
| 3106 | * command session. | ||
| 3107 | **/ | ||
| 3108 | static void | ||
| 3109 | lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba) | ||
| 3110 | { | ||
| 3111 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) | ||
| 3112 | return; | ||
| 3113 | |||
| 3114 | /* free all memory, including dma buffers */ | ||
| 3115 | lpfc_bsg_dma_page_list_free(phba, | ||
| 3116 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 3117 | lpfc_bsg_dma_page_free(phba, phba->mbox_ext_buf_ctx.mbx_dmabuf); | ||
| 3118 | /* multi-buffer write mailbox command pass-through complete */ | ||
| 3119 | memset((char *)&phba->mbox_ext_buf_ctx, 0, | ||
| 3120 | sizeof(struct lpfc_mbox_ext_buf_ctx)); | ||
| 3121 | INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 3122 | |||
| 3123 | return; | ||
| 3124 | } | ||
| 3125 | |||
| 3126 | /** | ||
| 3127 | * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl | ||
| 3128 | * @phba: Pointer to HBA context object. | ||
| 3129 | * @pmboxq: Pointer to mailbox command. | ||
| 3130 | * | ||
| 3131 | * This is routine handles BSG job for mailbox commands completions with | ||
| 3132 | * multiple external buffers. | ||
| 3133 | **/ | ||
| 3134 | static struct fc_bsg_job * | ||
| 3135 | lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
| 3136 | { | ||
| 3137 | struct bsg_job_data *dd_data; | ||
| 3138 | struct fc_bsg_job *job; | ||
| 3139 | uint8_t *pmb, *pmb_buf; | ||
| 3140 | unsigned long flags; | ||
| 3141 | uint32_t size; | ||
| 3142 | int rc = 0; | ||
| 3143 | |||
| 3144 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | ||
| 3145 | dd_data = pmboxq->context1; | ||
| 3146 | /* has the job already timed out? */ | ||
| 3147 | if (!dd_data) { | ||
| 3148 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 3149 | job = NULL; | ||
| 3150 | goto job_done_out; | ||
| 3151 | } | ||
| 3152 | |||
| 3153 | /* | ||
| 3154 | * The outgoing buffer is readily referred from the dma buffer, | ||
| 3155 | * just need to get header part from mailboxq structure. | ||
| 3156 | */ | ||
| 3157 | pmb = (uint8_t *)&pmboxq->u.mb; | ||
| 3158 | pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb; | ||
| 3159 | memcpy(pmb_buf, pmb, sizeof(MAILBOX_t)); | ||
| 3160 | |||
| 3161 | job = dd_data->context_un.mbox.set_job; | ||
| 3162 | if (job) { | ||
| 3163 | size = job->reply_payload.payload_len; | ||
| 3164 | job->reply->reply_payload_rcv_len = | ||
| 3165 | sg_copy_from_buffer(job->reply_payload.sg_list, | ||
| 3166 | job->reply_payload.sg_cnt, | ||
| 3167 | pmb_buf, size); | ||
| 3168 | /* result for successful */ | ||
| 3169 | job->reply->result = 0; | ||
| 3170 | job->dd_data = NULL; | ||
| 3171 | /* need to hold the lock util we set job->dd_data to NULL | ||
| 3172 | * to hold off the timeout handler from midlayer to take | ||
| 3173 | * any action. | ||
| 3174 | */ | ||
| 3175 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 3176 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3177 | "2937 SLI_CONFIG ext-buffer maibox command " | ||
| 3178 | "(x%x/x%x) complete bsg job done, bsize:%d\n", | ||
| 3179 | phba->mbox_ext_buf_ctx.nembType, | ||
| 3180 | phba->mbox_ext_buf_ctx.mboxType, size); | ||
| 3181 | } else | ||
| 3182 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
| 3183 | |||
| 3184 | job_done_out: | ||
| 3185 | if (!job) | ||
| 3186 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3187 | "2938 SLI_CONFIG ext-buffer maibox " | ||
| 3188 | "command (x%x/x%x) failure, rc:x%x\n", | ||
| 3189 | phba->mbox_ext_buf_ctx.nembType, | ||
| 3190 | phba->mbox_ext_buf_ctx.mboxType, rc); | ||
| 3191 | /* state change */ | ||
| 3192 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_DONE; | ||
| 3193 | kfree(dd_data); | ||
| 3194 | |||
| 3195 | return job; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | /** | ||
| 3199 | * lpfc_bsg_issue_read_mbox_ext_cmpl - compl handler for multi-buffer read mbox | ||
| 3200 | * @phba: Pointer to HBA context object. | ||
| 3201 | * @pmboxq: Pointer to mailbox command. | ||
| 3202 | * | ||
| 3203 | * This is completion handler function for mailbox read commands with multiple | ||
| 3204 | * external buffers. | ||
| 3205 | **/ | ||
| 3206 | static void | ||
| 3207 | lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
| 3208 | { | ||
| 3209 | struct fc_bsg_job *job; | ||
| 3210 | |||
| 3211 | /* handle the BSG job with mailbox command */ | ||
| 3212 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS) | ||
| 3213 | pmboxq->u.mb.mbxStatus = MBXERR_ERROR; | ||
| 3214 | |||
| 3215 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3216 | "2939 SLI_CONFIG ext-buffer rd maibox command " | ||
| 3217 | "complete, ctxState:x%x, mbxStatus:x%x\n", | ||
| 3218 | phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus); | ||
| 3219 | |||
| 3220 | job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); | ||
| 3221 | |||
| 3222 | if (pmboxq->u.mb.mbxStatus || phba->mbox_ext_buf_ctx.numBuf == 1) | ||
| 3223 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
| 3224 | |||
| 3225 | /* free base driver mailbox structure memory */ | ||
| 3226 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 3227 | |||
| 3228 | /* complete the bsg job if we have it */ | ||
| 3229 | if (job) | ||
| 3230 | job->job_done(job); | ||
| 3231 | |||
| 3232 | return; | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | /** | ||
| 3236 | * lpfc_bsg_issue_write_mbox_ext_cmpl - cmpl handler for multi-buffer write mbox | ||
| 3237 | * @phba: Pointer to HBA context object. | ||
| 3238 | * @pmboxq: Pointer to mailbox command. | ||
| 3239 | * | ||
| 3240 | * This is completion handler function for mailbox write commands with multiple | ||
| 3241 | * external buffers. | ||
| 3242 | **/ | ||
| 3243 | static void | ||
| 3244 | lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
| 3245 | { | ||
| 3246 | struct fc_bsg_job *job; | ||
| 3247 | |||
| 3248 | /* handle the BSG job with the mailbox command */ | ||
| 3249 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_ABTS) | ||
| 3250 | pmboxq->u.mb.mbxStatus = MBXERR_ERROR; | ||
| 3251 | |||
| 3252 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3253 | "2940 SLI_CONFIG ext-buffer wr maibox command " | ||
| 3254 | "complete, ctxState:x%x, mbxStatus:x%x\n", | ||
| 3255 | phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus); | ||
| 3256 | |||
| 3257 | job = lpfc_bsg_issue_mbox_ext_handle_job(phba, pmboxq); | ||
| 3258 | |||
| 3259 | /* free all memory, including dma buffers */ | ||
| 3260 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 3261 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
| 3262 | |||
| 3263 | /* complete the bsg job if we have it */ | ||
| 3264 | if (job) | ||
| 3265 | job->job_done(job); | ||
| 3266 | |||
| 3267 | return; | ||
| 3268 | } | ||
| 3269 | |||
| 3270 | static void | ||
| 3271 | lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp, | ||
| 3272 | uint32_t index, struct lpfc_dmabuf *mbx_dmabuf, | ||
| 3273 | struct lpfc_dmabuf *ext_dmabuf) | ||
| 3274 | { | ||
| 3275 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3276 | |||
| 3277 | /* pointer to the start of mailbox command */ | ||
| 3278 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)mbx_dmabuf->virt; | ||
| 3279 | |||
| 3280 | if (nemb_tp == nemb_mse) { | ||
| 3281 | if (index == 0) { | ||
| 3282 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3283 | mse[index].pa_hi = | ||
| 3284 | putPaddrHigh(mbx_dmabuf->phys + | ||
| 3285 | sizeof(MAILBOX_t)); | ||
| 3286 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3287 | mse[index].pa_lo = | ||
| 3288 | putPaddrLow(mbx_dmabuf->phys + | ||
| 3289 | sizeof(MAILBOX_t)); | ||
| 3290 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3291 | "2943 SLI_CONFIG(mse)[%d], " | ||
| 3292 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
| 3293 | index, | ||
| 3294 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3295 | mse[index].buf_len, | ||
| 3296 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3297 | mse[index].pa_hi, | ||
| 3298 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3299 | mse[index].pa_lo); | ||
| 3300 | } else { | ||
| 3301 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3302 | mse[index].pa_hi = | ||
| 3303 | putPaddrHigh(ext_dmabuf->phys); | ||
| 3304 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3305 | mse[index].pa_lo = | ||
| 3306 | putPaddrLow(ext_dmabuf->phys); | ||
| 3307 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3308 | "2944 SLI_CONFIG(mse)[%d], " | ||
| 3309 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
| 3310 | index, | ||
| 3311 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3312 | mse[index].buf_len, | ||
| 3313 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3314 | mse[index].pa_hi, | ||
| 3315 | sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3316 | mse[index].pa_lo); | ||
| 3317 | } | ||
| 3318 | } else { | ||
| 3319 | if (index == 0) { | ||
| 3320 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3321 | hbd[index].pa_hi = | ||
| 3322 | putPaddrHigh(mbx_dmabuf->phys + | ||
| 3323 | sizeof(MAILBOX_t)); | ||
| 3324 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3325 | hbd[index].pa_lo = | ||
| 3326 | putPaddrLow(mbx_dmabuf->phys + | ||
| 3327 | sizeof(MAILBOX_t)); | ||
| 3328 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3329 | "3007 SLI_CONFIG(hbd)[%d], " | ||
| 3330 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
| 3331 | index, | ||
| 3332 | bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
| 3333 | &sli_cfg_mbx->un. | ||
| 3334 | sli_config_emb1_subsys.hbd[index]), | ||
| 3335 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3336 | hbd[index].pa_hi, | ||
| 3337 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3338 | hbd[index].pa_lo); | ||
| 3339 | |||
| 3340 | } else { | ||
| 3341 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3342 | hbd[index].pa_hi = | ||
| 3343 | putPaddrHigh(ext_dmabuf->phys); | ||
| 3344 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3345 | hbd[index].pa_lo = | ||
| 3346 | putPaddrLow(ext_dmabuf->phys); | ||
| 3347 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3348 | "3008 SLI_CONFIG(hbd)[%d], " | ||
| 3349 | "bufLen:%d, addrHi:x%x, addrLo:x%x\n", | ||
| 3350 | index, | ||
| 3351 | bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
| 3352 | &sli_cfg_mbx->un. | ||
| 3353 | sli_config_emb1_subsys.hbd[index]), | ||
| 3354 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3355 | hbd[index].pa_hi, | ||
| 3356 | sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3357 | hbd[index].pa_lo); | ||
| 3358 | } | ||
| 3359 | } | ||
| 3360 | return; | ||
| 3361 | } | ||
| 3362 | |||
| 3363 | /** | ||
| 3364 | * lpfc_bsg_sli_cfg_mse_read_cmd_ext - sli_config non-embedded mailbox cmd read | ||
| 3365 | * @phba: Pointer to HBA context object. | ||
| 3366 | * @mb: Pointer to a BSG mailbox object. | ||
| 3367 | * @nemb_tp: Enumerate of non-embedded mailbox command type. | ||
| 3368 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
| 3369 | * | ||
| 3370 | * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with | ||
| 3371 | * non-embedded external bufffers. | ||
| 3372 | **/ | ||
| 3373 | static int | ||
| 3374 | lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 3375 | enum nemb_type nemb_tp, | ||
| 3376 | struct lpfc_dmabuf *dmabuf) | ||
| 3377 | { | ||
| 3378 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3379 | struct dfc_mbox_req *mbox_req; | ||
| 3380 | struct lpfc_dmabuf *curr_dmabuf, *next_dmabuf; | ||
| 3381 | uint32_t ext_buf_cnt, ext_buf_index; | ||
| 3382 | struct lpfc_dmabuf *ext_dmabuf = NULL; | ||
| 3383 | struct bsg_job_data *dd_data = NULL; | ||
| 3384 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
| 3385 | MAILBOX_t *pmb; | ||
| 3386 | uint8_t *pmbx; | ||
| 3387 | int rc, i; | ||
| 3388 | |||
| 3389 | mbox_req = | ||
| 3390 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 3391 | |||
| 3392 | /* pointer to the start of mailbox command */ | ||
| 3393 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
| 3394 | |||
| 3395 | if (nemb_tp == nemb_mse) { | ||
| 3396 | ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt, | ||
| 3397 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr); | ||
| 3398 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) { | ||
| 3399 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3400 | "2945 Handled SLI_CONFIG(mse) rd, " | ||
| 3401 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
| 3402 | ext_buf_cnt, | ||
| 3403 | LPFC_MBX_SLI_CONFIG_MAX_MSE); | ||
| 3404 | rc = -ERANGE; | ||
| 3405 | goto job_error; | ||
| 3406 | } | ||
| 3407 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3408 | "2941 Handled SLI_CONFIG(mse) rd, " | ||
| 3409 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
| 3410 | } else { | ||
| 3411 | /* sanity check on interface type for support */ | ||
| 3412 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 3413 | LPFC_SLI_INTF_IF_TYPE_2) { | ||
| 3414 | rc = -ENODEV; | ||
| 3415 | goto job_error; | ||
| 3416 | } | ||
| 3417 | /* nemb_tp == nemb_hbd */ | ||
| 3418 | ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count; | ||
| 3419 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) { | ||
| 3420 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3421 | "2946 Handled SLI_CONFIG(hbd) rd, " | ||
| 3422 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
| 3423 | ext_buf_cnt, | ||
| 3424 | LPFC_MBX_SLI_CONFIG_MAX_HBD); | ||
| 3425 | rc = -ERANGE; | ||
| 3426 | goto job_error; | ||
| 3427 | } | ||
| 3428 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3429 | "2942 Handled SLI_CONFIG(hbd) rd, " | ||
| 3430 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
| 3431 | } | ||
| 3432 | |||
| 3433 | /* reject non-embedded mailbox command with none external buffer */ | ||
| 3434 | if (ext_buf_cnt == 0) { | ||
| 3435 | rc = -EPERM; | ||
| 3436 | goto job_error; | ||
| 3437 | } else if (ext_buf_cnt > 1) { | ||
| 3438 | /* additional external read buffers */ | ||
| 3439 | for (i = 1; i < ext_buf_cnt; i++) { | ||
| 3440 | ext_dmabuf = lpfc_bsg_dma_page_alloc(phba); | ||
| 3441 | if (!ext_dmabuf) { | ||
| 3442 | rc = -ENOMEM; | ||
| 3443 | goto job_error; | ||
| 3444 | } | ||
| 3445 | list_add_tail(&ext_dmabuf->list, | ||
| 3446 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 3447 | } | ||
| 3448 | } | ||
| 3449 | |||
| 3450 | /* bsg tracking structure */ | ||
| 3451 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
| 3452 | if (!dd_data) { | ||
| 3453 | rc = -ENOMEM; | ||
| 3454 | goto job_error; | ||
| 3455 | } | ||
| 3456 | |||
| 3457 | /* mailbox command structure for base driver */ | ||
| 3458 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 3459 | if (!pmboxq) { | ||
| 3460 | rc = -ENOMEM; | ||
| 3461 | goto job_error; | ||
| 3462 | } | ||
| 3463 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
| 3464 | |||
| 3465 | /* for the first external buffer */ | ||
| 3466 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); | ||
| 3467 | |||
| 3468 | /* for the rest of external buffer descriptors if any */ | ||
| 3469 | if (ext_buf_cnt > 1) { | ||
| 3470 | ext_buf_index = 1; | ||
| 3471 | list_for_each_entry_safe(curr_dmabuf, next_dmabuf, | ||
| 3472 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list, list) { | ||
| 3473 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, | ||
| 3474 | ext_buf_index, dmabuf, | ||
| 3475 | curr_dmabuf); | ||
| 3476 | ext_buf_index++; | ||
| 3477 | } | ||
| 3478 | } | ||
| 3479 | |||
| 3480 | /* construct base driver mbox command */ | ||
| 3481 | pmb = &pmboxq->u.mb; | ||
| 3482 | pmbx = (uint8_t *)dmabuf->virt; | ||
| 3483 | memcpy(pmb, pmbx, sizeof(*pmb)); | ||
| 3484 | pmb->mbxOwner = OWN_HOST; | ||
| 3485 | pmboxq->vport = phba->pport; | ||
| 3486 | |||
| 3487 | /* multi-buffer handling context */ | ||
| 3488 | phba->mbox_ext_buf_ctx.nembType = nemb_tp; | ||
| 3489 | phba->mbox_ext_buf_ctx.mboxType = mbox_rd; | ||
| 3490 | phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt; | ||
| 3491 | phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag; | ||
| 3492 | phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum; | ||
| 3493 | phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf; | ||
| 3494 | |||
| 3495 | /* callback for multi-buffer read mailbox command */ | ||
| 3496 | pmboxq->mbox_cmpl = lpfc_bsg_issue_read_mbox_ext_cmpl; | ||
| 3497 | |||
| 3498 | /* context fields to callback function */ | ||
| 3499 | pmboxq->context1 = dd_data; | ||
| 3500 | dd_data->type = TYPE_MBOX; | ||
| 3501 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
| 3502 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx; | ||
| 3503 | dd_data->context_un.mbox.set_job = job; | ||
| 3504 | job->dd_data = dd_data; | ||
| 3505 | |||
| 3506 | /* state change */ | ||
| 3507 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
| 3508 | |||
| 3509 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
| 3510 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
| 3511 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3512 | "2947 Issued SLI_CONFIG ext-buffer " | ||
| 3513 | "maibox command, rc:x%x\n", rc); | ||
| 3514 | return 1; | ||
| 3515 | } | ||
| 3516 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3517 | "2948 Failed to issue SLI_CONFIG ext-buffer " | ||
| 3518 | "maibox command, rc:x%x\n", rc); | ||
| 3519 | rc = -EPIPE; | ||
| 3520 | |||
| 3521 | job_error: | ||
| 3522 | if (pmboxq) | ||
| 3523 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 3524 | lpfc_bsg_dma_page_list_free(phba, | ||
| 3525 | &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 3526 | kfree(dd_data); | ||
| 3527 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE; | ||
| 3528 | return rc; | ||
| 3529 | } | ||
| 3530 | |||
| 3531 | /** | ||
| 3532 | * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write | ||
| 3533 | * @phba: Pointer to HBA context object. | ||
| 3534 | * @mb: Pointer to a BSG mailbox object. | ||
| 3535 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
| 3536 | * | ||
| 3537 | * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with | ||
| 3538 | * non-embedded external bufffers. | ||
| 3539 | **/ | ||
| 3540 | static int | ||
| 3541 | lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 3542 | enum nemb_type nemb_tp, | ||
| 3543 | struct lpfc_dmabuf *dmabuf) | ||
| 3544 | { | ||
| 3545 | struct dfc_mbox_req *mbox_req; | ||
| 3546 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3547 | uint32_t ext_buf_cnt; | ||
| 3548 | struct bsg_job_data *dd_data = NULL; | ||
| 3549 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
| 3550 | MAILBOX_t *pmb; | ||
| 3551 | uint8_t *mbx; | ||
| 3552 | int rc = 0, i; | ||
| 3553 | |||
| 3554 | mbox_req = | ||
| 3555 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 3556 | |||
| 3557 | /* pointer to the start of mailbox command */ | ||
| 3558 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
| 3559 | |||
| 3560 | if (nemb_tp == nemb_mse) { | ||
| 3561 | ext_buf_cnt = bsg_bf_get(lpfc_mbox_hdr_mse_cnt, | ||
| 3562 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr); | ||
| 3563 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) { | ||
| 3564 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3565 | "2953 Handled SLI_CONFIG(mse) wr, " | ||
| 3566 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
| 3567 | ext_buf_cnt, | ||
| 3568 | LPFC_MBX_SLI_CONFIG_MAX_MSE); | ||
| 3569 | return -ERANGE; | ||
| 3570 | } | ||
| 3571 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3572 | "2949 Handled SLI_CONFIG(mse) wr, " | ||
| 3573 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
| 3574 | } else { | ||
| 3575 | /* sanity check on interface type for support */ | ||
| 3576 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 3577 | LPFC_SLI_INTF_IF_TYPE_2) | ||
| 3578 | return -ENODEV; | ||
| 3579 | /* nemb_tp == nemb_hbd */ | ||
| 3580 | ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count; | ||
| 3581 | if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) { | ||
| 3582 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3583 | "2954 Handled SLI_CONFIG(hbd) wr, " | ||
| 3584 | "ext_buf_cnt(%d) out of range(%d)\n", | ||
| 3585 | ext_buf_cnt, | ||
| 3586 | LPFC_MBX_SLI_CONFIG_MAX_HBD); | ||
| 3587 | return -ERANGE; | ||
| 3588 | } | ||
| 3589 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3590 | "2950 Handled SLI_CONFIG(hbd) wr, " | ||
| 3591 | "ext_buf_cnt:%d\n", ext_buf_cnt); | ||
| 3592 | } | ||
| 3593 | |||
| 3594 | if (ext_buf_cnt == 0) | ||
| 3595 | return -EPERM; | ||
| 3596 | |||
| 3597 | /* for the first external buffer */ | ||
| 3598 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); | ||
| 3599 | |||
| 3600 | /* log for looking forward */ | ||
| 3601 | for (i = 1; i < ext_buf_cnt; i++) { | ||
| 3602 | if (nemb_tp == nemb_mse) | ||
| 3603 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3604 | "2951 SLI_CONFIG(mse), buf[%d]-length:%d\n", | ||
| 3605 | i, sli_cfg_mbx->un.sli_config_emb0_subsys. | ||
| 3606 | mse[i].buf_len); | ||
| 3607 | else | ||
| 3608 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3609 | "2952 SLI_CONFIG(hbd), buf[%d]-length:%d\n", | ||
| 3610 | i, bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
| 3611 | &sli_cfg_mbx->un.sli_config_emb1_subsys. | ||
| 3612 | hbd[i])); | ||
| 3613 | } | ||
| 3614 | |||
| 3615 | /* multi-buffer handling context */ | ||
| 3616 | phba->mbox_ext_buf_ctx.nembType = nemb_tp; | ||
| 3617 | phba->mbox_ext_buf_ctx.mboxType = mbox_wr; | ||
| 3618 | phba->mbox_ext_buf_ctx.numBuf = ext_buf_cnt; | ||
| 3619 | phba->mbox_ext_buf_ctx.mbxTag = mbox_req->extMboxTag; | ||
| 3620 | phba->mbox_ext_buf_ctx.seqNum = mbox_req->extSeqNum; | ||
| 3621 | phba->mbox_ext_buf_ctx.mbx_dmabuf = dmabuf; | ||
| 3622 | |||
| 3623 | if (ext_buf_cnt == 1) { | ||
| 3624 | /* bsg tracking structure */ | ||
| 3625 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
| 3626 | if (!dd_data) { | ||
| 3627 | rc = -ENOMEM; | ||
| 3628 | goto job_error; | ||
| 3629 | } | ||
| 3630 | |||
| 3631 | /* mailbox command structure for base driver */ | ||
| 3632 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 3633 | if (!pmboxq) { | ||
| 3634 | rc = -ENOMEM; | ||
| 3635 | goto job_error; | ||
| 3636 | } | ||
| 3637 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
| 3638 | pmb = &pmboxq->u.mb; | ||
| 3639 | mbx = (uint8_t *)dmabuf->virt; | ||
| 3640 | memcpy(pmb, mbx, sizeof(*pmb)); | ||
| 3641 | pmb->mbxOwner = OWN_HOST; | ||
| 3642 | pmboxq->vport = phba->pport; | ||
| 3643 | |||
| 3644 | /* callback for multi-buffer read mailbox command */ | ||
| 3645 | pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl; | ||
| 3646 | |||
| 3647 | /* context fields to callback function */ | ||
| 3648 | pmboxq->context1 = dd_data; | ||
| 3649 | dd_data->type = TYPE_MBOX; | ||
| 3650 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
| 3651 | dd_data->context_un.mbox.mb = (MAILBOX_t *)mbx; | ||
| 3652 | dd_data->context_un.mbox.set_job = job; | ||
| 3653 | job->dd_data = dd_data; | ||
| 3654 | |||
| 3655 | /* state change */ | ||
| 3656 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
| 3657 | |||
| 3658 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
| 3659 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
| 3660 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3661 | "2955 Issued SLI_CONFIG ext-buffer " | ||
| 3662 | "maibox command, rc:x%x\n", rc); | ||
| 3663 | return 1; | ||
| 3664 | } | ||
| 3665 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3666 | "2956 Failed to issue SLI_CONFIG ext-buffer " | ||
| 3667 | "maibox command, rc:x%x\n", rc); | ||
| 3668 | rc = -EPIPE; | ||
| 3669 | } | ||
| 3670 | |||
| 3671 | job_error: | ||
| 3672 | if (pmboxq) | ||
| 3673 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 3674 | kfree(dd_data); | ||
| 3675 | |||
| 3676 | return rc; | ||
| 3677 | } | ||
| 3678 | |||
| 3679 | /** | ||
| 3680 | * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer | ||
| 3681 | * @phba: Pointer to HBA context object. | ||
| 3682 | * @mb: Pointer to a BSG mailbox object. | ||
| 3683 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
| 3684 | * | ||
| 3685 | * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded | ||
| 3686 | * external bufffers, including both 0x9B with non-embedded MSEs and 0x9B | ||
| 3687 | * with embedded sussystem 0x1 and opcodes with external HBDs. | ||
| 3688 | **/ | ||
| 3689 | static int | ||
| 3690 | lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 3691 | struct lpfc_dmabuf *dmabuf) | ||
| 3692 | { | ||
| 3693 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3694 | uint32_t subsys; | ||
| 3695 | uint32_t opcode; | ||
| 3696 | int rc = SLI_CONFIG_NOT_HANDLED; | ||
| 3697 | |||
| 3698 | /* state change */ | ||
| 3699 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST; | ||
| 3700 | |||
| 3701 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; | ||
| 3702 | |||
| 3703 | if (!bsg_bf_get(lpfc_mbox_hdr_emb, | ||
| 3704 | &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) { | ||
| 3705 | subsys = bsg_bf_get(lpfc_emb0_subcmnd_subsys, | ||
| 3706 | &sli_cfg_mbx->un.sli_config_emb0_subsys); | ||
| 3707 | opcode = bsg_bf_get(lpfc_emb0_subcmnd_opcode, | ||
| 3708 | &sli_cfg_mbx->un.sli_config_emb0_subsys); | ||
| 3709 | if (subsys == SLI_CONFIG_SUBSYS_FCOE) { | ||
| 3710 | switch (opcode) { | ||
| 3711 | case FCOE_OPCODE_READ_FCF: | ||
| 3712 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3713 | "2957 Handled SLI_CONFIG " | ||
| 3714 | "subsys_fcoe, opcode:x%x\n", | ||
| 3715 | opcode); | ||
| 3716 | rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, | ||
| 3717 | nemb_mse, dmabuf); | ||
| 3718 | break; | ||
| 3719 | case FCOE_OPCODE_ADD_FCF: | ||
| 3720 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3721 | "2958 Handled SLI_CONFIG " | ||
| 3722 | "subsys_fcoe, opcode:x%x\n", | ||
| 3723 | opcode); | ||
| 3724 | rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job, | ||
| 3725 | nemb_mse, dmabuf); | ||
| 3726 | break; | ||
| 3727 | default: | ||
| 3728 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3729 | "2959 Not handled SLI_CONFIG " | ||
| 3730 | "subsys_fcoe, opcode:x%x\n", | ||
| 3731 | opcode); | ||
| 3732 | rc = SLI_CONFIG_NOT_HANDLED; | ||
| 3733 | break; | ||
| 3734 | } | ||
| 3735 | } else { | ||
| 3736 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3737 | "2977 Handled SLI_CONFIG " | ||
| 3738 | "subsys:x%d, opcode:x%x\n", | ||
| 3739 | subsys, opcode); | ||
| 3740 | rc = SLI_CONFIG_NOT_HANDLED; | ||
| 3741 | } | ||
| 3742 | } else { | ||
| 3743 | subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys, | ||
| 3744 | &sli_cfg_mbx->un.sli_config_emb1_subsys); | ||
| 3745 | opcode = bsg_bf_get(lpfc_emb1_subcmnd_opcode, | ||
| 3746 | &sli_cfg_mbx->un.sli_config_emb1_subsys); | ||
| 3747 | if (subsys == SLI_CONFIG_SUBSYS_COMN) { | ||
| 3748 | switch (opcode) { | ||
| 3749 | case COMN_OPCODE_READ_OBJECT: | ||
| 3750 | case COMN_OPCODE_READ_OBJECT_LIST: | ||
| 3751 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3752 | "2960 Handled SLI_CONFIG " | ||
| 3753 | "subsys_comn, opcode:x%x\n", | ||
| 3754 | opcode); | ||
| 3755 | rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, | ||
| 3756 | nemb_hbd, dmabuf); | ||
| 3757 | break; | ||
| 3758 | case COMN_OPCODE_WRITE_OBJECT: | ||
| 3759 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3760 | "2961 Handled SLI_CONFIG " | ||
| 3761 | "subsys_comn, opcode:x%x\n", | ||
| 3762 | opcode); | ||
| 3763 | rc = lpfc_bsg_sli_cfg_write_cmd_ext(phba, job, | ||
| 3764 | nemb_hbd, dmabuf); | ||
| 3765 | break; | ||
| 3766 | default: | ||
| 3767 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3768 | "2962 Not handled SLI_CONFIG " | ||
| 3769 | "subsys_comn, opcode:x%x\n", | ||
| 3770 | opcode); | ||
| 3771 | rc = SLI_CONFIG_NOT_HANDLED; | ||
| 3772 | break; | ||
| 3773 | } | ||
| 3774 | } else { | ||
| 3775 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3776 | "2978 Handled SLI_CONFIG " | ||
| 3777 | "subsys:x%d, opcode:x%x\n", | ||
| 3778 | subsys, opcode); | ||
| 3779 | rc = SLI_CONFIG_NOT_HANDLED; | ||
| 3780 | } | ||
| 3781 | } | ||
| 3782 | return rc; | ||
| 3783 | } | ||
| 3784 | |||
| 3785 | /** | ||
| 3786 | * lpfc_bsg_mbox_ext_abort_req - request to abort mbox command with ext buffers | ||
| 3787 | * @phba: Pointer to HBA context object. | ||
| 3788 | * | ||
| 3789 | * This routine is for requesting to abort a pass-through mailbox command with | ||
| 3790 | * multiple external buffers due to error condition. | ||
| 3791 | **/ | ||
| 3792 | static void | ||
| 3793 | lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba) | ||
| 3794 | { | ||
| 3795 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT) | ||
| 3796 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS; | ||
| 3797 | else | ||
| 3798 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
| 3799 | return; | ||
| 3800 | } | ||
| 3801 | |||
| 3802 | /** | ||
| 3803 | * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer | ||
| 3804 | * @phba: Pointer to HBA context object. | ||
| 3805 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
| 3806 | * | ||
| 3807 | * This routine extracts the next mailbox read external buffer back to | ||
| 3808 | * user space through BSG. | ||
| 3809 | **/ | ||
| 3810 | static int | ||
| 3811 | lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) | ||
| 3812 | { | ||
| 3813 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3814 | struct lpfc_dmabuf *dmabuf; | ||
| 3815 | uint8_t *pbuf; | ||
| 3816 | uint32_t size; | ||
| 3817 | uint32_t index; | ||
| 3818 | |||
| 3819 | index = phba->mbox_ext_buf_ctx.seqNum; | ||
| 3820 | phba->mbox_ext_buf_ctx.seqNum++; | ||
| 3821 | |||
| 3822 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *) | ||
| 3823 | phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
| 3824 | |||
| 3825 | if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) { | ||
| 3826 | size = bsg_bf_get(lpfc_mbox_sli_config_mse_len, | ||
| 3827 | &sli_cfg_mbx->un.sli_config_emb0_subsys.mse[index]); | ||
| 3828 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3829 | "2963 SLI_CONFIG (mse) ext-buffer rd get " | ||
| 3830 | "buffer[%d], size:%d\n", index, size); | ||
| 3831 | } else { | ||
| 3832 | size = bsg_bf_get(lpfc_mbox_sli_config_ecmn_hbd_len, | ||
| 3833 | &sli_cfg_mbx->un.sli_config_emb1_subsys.hbd[index]); | ||
| 3834 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3835 | "2964 SLI_CONFIG (hbd) ext-buffer rd get " | ||
| 3836 | "buffer[%d], size:%d\n", index, size); | ||
| 3837 | } | ||
| 3838 | if (list_empty(&phba->mbox_ext_buf_ctx.ext_dmabuf_list)) | ||
| 3839 | return -EPIPE; | ||
| 3840 | dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list, | ||
| 3841 | struct lpfc_dmabuf, list); | ||
| 3842 | list_del_init(&dmabuf->list); | ||
| 3843 | pbuf = (uint8_t *)dmabuf->virt; | ||
| 3844 | job->reply->reply_payload_rcv_len = | ||
| 3845 | sg_copy_from_buffer(job->reply_payload.sg_list, | ||
| 3846 | job->reply_payload.sg_cnt, | ||
| 3847 | pbuf, size); | ||
| 3848 | |||
| 3849 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
| 3850 | |||
| 3851 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { | ||
| 3852 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3853 | "2965 SLI_CONFIG (hbd) ext-buffer rd mbox " | ||
| 3854 | "command session done\n"); | ||
| 3855 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
| 3856 | } | ||
| 3857 | |||
| 3858 | job->reply->result = 0; | ||
| 3859 | job->job_done(job); | ||
| 3860 | |||
| 3861 | return SLI_CONFIG_HANDLED; | ||
| 3862 | } | ||
| 3863 | |||
| 3864 | /** | ||
| 3865 | * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer | ||
| 3866 | * @phba: Pointer to HBA context object. | ||
| 3867 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
| 3868 | * | ||
| 3869 | * This routine sets up the next mailbox read external buffer obtained | ||
| 3870 | * from user space through BSG. | ||
| 3871 | **/ | ||
| 3872 | static int | ||
| 3873 | lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 3874 | struct lpfc_dmabuf *dmabuf) | ||
| 3875 | { | ||
| 3876 | struct lpfc_sli_config_mbox *sli_cfg_mbx; | ||
| 3877 | struct bsg_job_data *dd_data = NULL; | ||
| 3878 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
| 3879 | MAILBOX_t *pmb; | ||
| 3880 | enum nemb_type nemb_tp; | ||
| 3881 | uint8_t *pbuf; | ||
| 3882 | uint32_t size; | ||
| 3883 | uint32_t index; | ||
| 3884 | int rc; | ||
| 3885 | |||
| 3886 | index = phba->mbox_ext_buf_ctx.seqNum; | ||
| 3887 | phba->mbox_ext_buf_ctx.seqNum++; | ||
| 3888 | nemb_tp = phba->mbox_ext_buf_ctx.nembType; | ||
| 3889 | |||
| 3890 | sli_cfg_mbx = (struct lpfc_sli_config_mbox *) | ||
| 3891 | phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
| 3892 | |||
| 3893 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | ||
| 3894 | if (!dd_data) { | ||
| 3895 | rc = -ENOMEM; | ||
| 3896 | goto job_error; | ||
| 3897 | } | ||
| 3898 | |||
| 3899 | pbuf = (uint8_t *)dmabuf->virt; | ||
| 3900 | size = job->request_payload.payload_len; | ||
| 3901 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
| 3902 | job->request_payload.sg_cnt, | ||
| 3903 | pbuf, size); | ||
| 3904 | |||
| 3905 | if (phba->mbox_ext_buf_ctx.nembType == nemb_mse) { | ||
| 3906 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3907 | "2966 SLI_CONFIG (mse) ext-buffer wr set " | ||
| 3908 | "buffer[%d], size:%d\n", | ||
| 3909 | phba->mbox_ext_buf_ctx.seqNum, size); | ||
| 3910 | |||
| 3911 | } else { | ||
| 3912 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3913 | "2967 SLI_CONFIG (hbd) ext-buffer wr set " | ||
| 3914 | "buffer[%d], size:%d\n", | ||
| 3915 | phba->mbox_ext_buf_ctx.seqNum, size); | ||
| 3916 | |||
| 3917 | } | ||
| 3918 | |||
| 3919 | /* set up external buffer descriptor and add to external buffer list */ | ||
| 3920 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, index, | ||
| 3921 | phba->mbox_ext_buf_ctx.mbx_dmabuf, | ||
| 3922 | dmabuf); | ||
| 3923 | list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 3924 | |||
| 3925 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { | ||
| 3926 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3927 | "2968 SLI_CONFIG ext-buffer wr all %d " | ||
| 3928 | "ebuffers received\n", | ||
| 3929 | phba->mbox_ext_buf_ctx.numBuf); | ||
| 3930 | /* mailbox command structure for base driver */ | ||
| 3931 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 3932 | if (!pmboxq) { | ||
| 3933 | rc = -ENOMEM; | ||
| 3934 | goto job_error; | ||
| 3935 | } | ||
| 3936 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
| 3937 | pbuf = (uint8_t *)phba->mbox_ext_buf_ctx.mbx_dmabuf->virt; | ||
| 3938 | pmb = &pmboxq->u.mb; | ||
| 3939 | memcpy(pmb, pbuf, sizeof(*pmb)); | ||
| 3940 | pmb->mbxOwner = OWN_HOST; | ||
| 3941 | pmboxq->vport = phba->pport; | ||
| 3942 | |||
| 3943 | /* callback for multi-buffer write mailbox command */ | ||
| 3944 | pmboxq->mbox_cmpl = lpfc_bsg_issue_write_mbox_ext_cmpl; | ||
| 3945 | |||
| 3946 | /* context fields to callback function */ | ||
| 3947 | pmboxq->context1 = dd_data; | ||
| 3948 | dd_data->type = TYPE_MBOX; | ||
| 3949 | dd_data->context_un.mbox.pmboxq = pmboxq; | ||
| 3950 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pbuf; | ||
| 3951 | dd_data->context_un.mbox.set_job = job; | ||
| 3952 | job->dd_data = dd_data; | ||
| 3953 | |||
| 3954 | /* state change */ | ||
| 3955 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; | ||
| 3956 | |||
| 3957 | rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
| 3958 | if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { | ||
| 3959 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3960 | "2969 Issued SLI_CONFIG ext-buffer " | ||
| 3961 | "maibox command, rc:x%x\n", rc); | ||
| 3962 | return 1; | ||
| 3963 | } | ||
| 3964 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 3965 | "2970 Failed to issue SLI_CONFIG ext-buffer " | ||
| 3966 | "maibox command, rc:x%x\n", rc); | ||
| 3967 | rc = -EPIPE; | ||
| 3968 | goto job_error; | ||
| 3969 | } | ||
| 3970 | |||
| 3971 | /* wait for additoinal external buffers */ | ||
| 3972 | job->reply->result = 0; | ||
| 3973 | job->job_done(job); | ||
| 3974 | return SLI_CONFIG_HANDLED; | ||
| 3975 | |||
| 3976 | job_error: | ||
| 3977 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
| 3978 | kfree(dd_data); | ||
| 3979 | |||
| 3980 | return rc; | ||
| 3981 | } | ||
| 3982 | |||
| 3983 | /** | ||
| 3984 | * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd | ||
| 3985 | * @phba: Pointer to HBA context object. | ||
| 3986 | * @mb: Pointer to a BSG mailbox object. | ||
| 3987 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
| 3988 | * | ||
| 3989 | * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox | ||
| 3990 | * command with multiple non-embedded external buffers. | ||
| 3991 | **/ | ||
| 3992 | static int | ||
| 3993 | lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 3994 | struct lpfc_dmabuf *dmabuf) | ||
| 3995 | { | ||
| 3996 | int rc; | ||
| 3997 | |||
| 3998 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 3999 | "2971 SLI_CONFIG buffer (type:x%x)\n", | ||
| 4000 | phba->mbox_ext_buf_ctx.mboxType); | ||
| 4001 | |||
| 4002 | if (phba->mbox_ext_buf_ctx.mboxType == mbox_rd) { | ||
| 4003 | if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_DONE) { | ||
| 4004 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 4005 | "2972 SLI_CONFIG rd buffer state " | ||
| 4006 | "mismatch:x%x\n", | ||
| 4007 | phba->mbox_ext_buf_ctx.state); | ||
| 4008 | lpfc_bsg_mbox_ext_abort(phba); | ||
| 4009 | return -EPIPE; | ||
| 4010 | } | ||
| 4011 | rc = lpfc_bsg_read_ebuf_get(phba, job); | ||
| 4012 | if (rc == SLI_CONFIG_HANDLED) | ||
| 4013 | lpfc_bsg_dma_page_free(phba, dmabuf); | ||
| 4014 | } else { /* phba->mbox_ext_buf_ctx.mboxType == mbox_wr */ | ||
| 4015 | if (phba->mbox_ext_buf_ctx.state != LPFC_BSG_MBOX_HOST) { | ||
| 4016 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 4017 | "2973 SLI_CONFIG wr buffer state " | ||
| 4018 | "mismatch:x%x\n", | ||
| 4019 | phba->mbox_ext_buf_ctx.state); | ||
| 4020 | lpfc_bsg_mbox_ext_abort(phba); | ||
| 4021 | return -EPIPE; | ||
| 4022 | } | ||
| 4023 | rc = lpfc_bsg_write_ebuf_set(phba, job, dmabuf); | ||
| 4024 | } | ||
| 4025 | return rc; | ||
| 4026 | } | ||
| 4027 | |||
| 4028 | /** | ||
| 4029 | * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer | ||
| 4030 | * @phba: Pointer to HBA context object. | ||
| 4031 | * @mb: Pointer to a BSG mailbox object. | ||
| 4032 | * @dmabuff: Pointer to a DMA buffer descriptor. | ||
| 4033 | * | ||
| 4034 | * This routine checkes and handles non-embedded multi-buffer SLI_CONFIG | ||
| 4035 | * (0x9B) mailbox commands and external buffers. | ||
| 4036 | **/ | ||
| 4037 | static int | ||
| 4038 | lpfc_bsg_handle_sli_cfg_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | ||
| 4039 | struct lpfc_dmabuf *dmabuf) | ||
| 4040 | { | ||
| 4041 | struct dfc_mbox_req *mbox_req; | ||
| 4042 | int rc; | ||
| 4043 | |||
| 4044 | mbox_req = | ||
| 4045 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 4046 | |||
| 4047 | /* mbox command with/without single external buffer */ | ||
| 4048 | if (mbox_req->extMboxTag == 0 && mbox_req->extSeqNum == 0) | ||
| 4049 | return SLI_CONFIG_NOT_HANDLED; | ||
| 4050 | |||
| 4051 | /* mbox command and first external buffer */ | ||
| 4052 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_IDLE) { | ||
| 4053 | if (mbox_req->extSeqNum == 1) { | ||
| 4054 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 4055 | "2974 SLI_CONFIG mailbox: tag:%d, " | ||
| 4056 | "seq:%d\n", mbox_req->extMboxTag, | ||
| 4057 | mbox_req->extSeqNum); | ||
| 4058 | rc = lpfc_bsg_handle_sli_cfg_mbox(phba, job, dmabuf); | ||
| 4059 | return rc; | ||
| 4060 | } else | ||
| 4061 | goto sli_cfg_ext_error; | ||
| 4062 | } | ||
| 4063 | |||
| 4064 | /* | ||
| 4065 | * handle additional external buffers | ||
| 4066 | */ | ||
| 4067 | |||
| 4068 | /* check broken pipe conditions */ | ||
| 4069 | if (mbox_req->extMboxTag != phba->mbox_ext_buf_ctx.mbxTag) | ||
| 4070 | goto sli_cfg_ext_error; | ||
| 4071 | if (mbox_req->extSeqNum > phba->mbox_ext_buf_ctx.numBuf) | ||
| 4072 | goto sli_cfg_ext_error; | ||
| 4073 | if (mbox_req->extSeqNum != phba->mbox_ext_buf_ctx.seqNum + 1) | ||
| 4074 | goto sli_cfg_ext_error; | ||
| 4075 | |||
| 4076 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
| 4077 | "2975 SLI_CONFIG mailbox external buffer: " | ||
| 4078 | "extSta:x%x, tag:%d, seq:%d\n", | ||
| 4079 | phba->mbox_ext_buf_ctx.state, mbox_req->extMboxTag, | ||
| 4080 | mbox_req->extSeqNum); | ||
| 4081 | rc = lpfc_bsg_handle_sli_cfg_ebuf(phba, job, dmabuf); | ||
| 4082 | return rc; | ||
| 4083 | |||
| 4084 | sli_cfg_ext_error: | ||
| 4085 | /* all other cases, broken pipe */ | ||
| 4086 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
| 4087 | "2976 SLI_CONFIG mailbox broken pipe: " | ||
| 4088 | "ctxSta:x%x, ctxNumBuf:%d " | ||
| 4089 | "ctxTag:%d, ctxSeq:%d, tag:%d, seq:%d\n", | ||
| 4090 | phba->mbox_ext_buf_ctx.state, | ||
| 4091 | phba->mbox_ext_buf_ctx.numBuf, | ||
| 4092 | phba->mbox_ext_buf_ctx.mbxTag, | ||
| 4093 | phba->mbox_ext_buf_ctx.seqNum, | ||
| 4094 | mbox_req->extMboxTag, mbox_req->extSeqNum); | ||
| 4095 | |||
| 4096 | lpfc_bsg_mbox_ext_session_reset(phba); | ||
| 4097 | |||
| 4098 | return -EPIPE; | ||
| 4099 | } | ||
| 4100 | |||
| 4101 | /** | ||
| 2622 | * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app | 4102 | * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app |
| 2623 | * @phba: Pointer to HBA context object. | 4103 | * @phba: Pointer to HBA context object. |
| 2624 | * @mb: Pointer to a mailbox object. | 4104 | * @mb: Pointer to a mailbox object. |
| @@ -2638,22 +4118,21 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2638 | LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ | 4118 | LPFC_MBOXQ_t *pmboxq = NULL; /* internal mailbox queue */ |
| 2639 | MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ | 4119 | MAILBOX_t *pmb; /* shortcut to the pmboxq mailbox */ |
| 2640 | /* a 4k buffer to hold the mb and extended data from/to the bsg */ | 4120 | /* a 4k buffer to hold the mb and extended data from/to the bsg */ |
| 2641 | MAILBOX_t *mb = NULL; | 4121 | uint8_t *pmbx = NULL; |
| 2642 | struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */ | 4122 | struct bsg_job_data *dd_data = NULL; /* bsg data tracking structure */ |
| 2643 | uint32_t size; | 4123 | struct lpfc_dmabuf *dmabuf = NULL; |
| 2644 | struct lpfc_dmabuf *rxbmp = NULL; /* for biu diag */ | 4124 | struct dfc_mbox_req *mbox_req; |
| 2645 | struct lpfc_dmabufext *dmp = NULL; /* for biu diag */ | ||
| 2646 | struct ulp_bde64 *rxbpl = NULL; | ||
| 2647 | struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *) | ||
| 2648 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 2649 | struct READ_EVENT_LOG_VAR *rdEventLog; | 4125 | struct READ_EVENT_LOG_VAR *rdEventLog; |
| 2650 | uint32_t transmit_length, receive_length, mode; | 4126 | uint32_t transmit_length, receive_length, mode; |
| 4127 | struct lpfc_mbx_sli4_config *sli4_config; | ||
| 2651 | struct lpfc_mbx_nembed_cmd *nembed_sge; | 4128 | struct lpfc_mbx_nembed_cmd *nembed_sge; |
| 2652 | struct mbox_header *header; | 4129 | struct mbox_header *header; |
| 2653 | struct ulp_bde64 *bde; | 4130 | struct ulp_bde64 *bde; |
| 2654 | uint8_t *ext = NULL; | 4131 | uint8_t *ext = NULL; |
| 2655 | int rc = 0; | 4132 | int rc = 0; |
| 2656 | uint8_t *from; | 4133 | uint8_t *from; |
| 4134 | uint32_t size; | ||
| 4135 | |||
| 2657 | 4136 | ||
| 2658 | /* in case no data is transferred */ | 4137 | /* in case no data is transferred */ |
| 2659 | job->reply->reply_payload_rcv_len = 0; | 4138 | job->reply->reply_payload_rcv_len = 0; |
| @@ -2665,6 +4144,18 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2665 | goto job_done; | 4144 | goto job_done; |
| 2666 | } | 4145 | } |
| 2667 | 4146 | ||
| 4147 | /* | ||
| 4148 | * Don't allow mailbox commands to be sent when blocked or when in | ||
| 4149 | * the middle of discovery | ||
| 4150 | */ | ||
| 4151 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
| 4152 | rc = -EAGAIN; | ||
| 4153 | goto job_done; | ||
| 4154 | } | ||
| 4155 | |||
| 4156 | mbox_req = | ||
| 4157 | (struct dfc_mbox_req *)job->request->rqst_data.h_vendor.vendor_cmd; | ||
| 4158 | |||
| 2668 | /* check if requested extended data lengths are valid */ | 4159 | /* check if requested extended data lengths are valid */ |
| 2669 | if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || | 4160 | if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || |
| 2670 | (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { | 4161 | (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { |
| @@ -2672,6 +4163,32 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2672 | goto job_done; | 4163 | goto job_done; |
| 2673 | } | 4164 | } |
| 2674 | 4165 | ||
| 4166 | dmabuf = lpfc_bsg_dma_page_alloc(phba); | ||
| 4167 | if (!dmabuf || !dmabuf->virt) { | ||
| 4168 | rc = -ENOMEM; | ||
| 4169 | goto job_done; | ||
| 4170 | } | ||
| 4171 | |||
| 4172 | /* Get the mailbox command or external buffer from BSG */ | ||
| 4173 | pmbx = (uint8_t *)dmabuf->virt; | ||
| 4174 | size = job->request_payload.payload_len; | ||
| 4175 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
| 4176 | job->request_payload.sg_cnt, pmbx, size); | ||
| 4177 | |||
| 4178 | /* Handle possible SLI_CONFIG with non-embedded payloads */ | ||
| 4179 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
| 4180 | rc = lpfc_bsg_handle_sli_cfg_ext(phba, job, dmabuf); | ||
| 4181 | if (rc == SLI_CONFIG_HANDLED) | ||
| 4182 | goto job_cont; | ||
| 4183 | if (rc) | ||
| 4184 | goto job_done; | ||
| 4185 | /* SLI_CONFIG_NOT_HANDLED for other mailbox commands */ | ||
| 4186 | } | ||
| 4187 | |||
| 4188 | rc = lpfc_bsg_check_cmd_access(phba, (MAILBOX_t *)pmbx, vport); | ||
| 4189 | if (rc != 0) | ||
| 4190 | goto job_done; /* must be negative */ | ||
| 4191 | |||
| 2675 | /* allocate our bsg tracking structure */ | 4192 | /* allocate our bsg tracking structure */ |
| 2676 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); | 4193 | dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); |
| 2677 | if (!dd_data) { | 4194 | if (!dd_data) { |
| @@ -2681,12 +4198,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2681 | goto job_done; | 4198 | goto job_done; |
| 2682 | } | 4199 | } |
| 2683 | 4200 | ||
| 2684 | mb = kzalloc(BSG_MBOX_SIZE, GFP_KERNEL); | ||
| 2685 | if (!mb) { | ||
| 2686 | rc = -ENOMEM; | ||
| 2687 | goto job_done; | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4201 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 2691 | if (!pmboxq) { | 4202 | if (!pmboxq) { |
| 2692 | rc = -ENOMEM; | 4203 | rc = -ENOMEM; |
| @@ -2694,17 +4205,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2694 | } | 4205 | } |
| 2695 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); | 4206 | memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); |
| 2696 | 4207 | ||
| 2697 | size = job->request_payload.payload_len; | ||
| 2698 | sg_copy_to_buffer(job->request_payload.sg_list, | ||
| 2699 | job->request_payload.sg_cnt, | ||
| 2700 | mb, size); | ||
| 2701 | |||
| 2702 | rc = lpfc_bsg_check_cmd_access(phba, mb, vport); | ||
| 2703 | if (rc != 0) | ||
| 2704 | goto job_done; /* must be negative */ | ||
| 2705 | |||
| 2706 | pmb = &pmboxq->u.mb; | 4208 | pmb = &pmboxq->u.mb; |
| 2707 | memcpy(pmb, mb, sizeof(*pmb)); | 4209 | memcpy(pmb, pmbx, sizeof(*pmb)); |
| 2708 | pmb->mbxOwner = OWN_HOST; | 4210 | pmb->mbxOwner = OWN_HOST; |
| 2709 | pmboxq->vport = vport; | 4211 | pmboxq->vport = vport; |
| 2710 | 4212 | ||
| @@ -2721,30 +4223,13 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2721 | "0x%x while in stopped state.\n", | 4223 | "0x%x while in stopped state.\n", |
| 2722 | pmb->mbxCommand); | 4224 | pmb->mbxCommand); |
| 2723 | 4225 | ||
| 2724 | /* Don't allow mailbox commands to be sent when blocked | ||
| 2725 | * or when in the middle of discovery | ||
| 2726 | */ | ||
| 2727 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
| 2728 | rc = -EAGAIN; | ||
| 2729 | goto job_done; | ||
| 2730 | } | ||
| 2731 | |||
| 2732 | /* extended mailbox commands will need an extended buffer */ | 4226 | /* extended mailbox commands will need an extended buffer */ |
| 2733 | if (mbox_req->inExtWLen || mbox_req->outExtWLen) { | 4227 | if (mbox_req->inExtWLen || mbox_req->outExtWLen) { |
| 2734 | ext = kzalloc(MAILBOX_EXT_SIZE, GFP_KERNEL); | ||
| 2735 | if (!ext) { | ||
| 2736 | rc = -ENOMEM; | ||
| 2737 | goto job_done; | ||
| 2738 | } | ||
| 2739 | |||
| 2740 | /* any data for the device? */ | 4228 | /* any data for the device? */ |
| 2741 | if (mbox_req->inExtWLen) { | 4229 | if (mbox_req->inExtWLen) { |
| 2742 | from = (uint8_t *)mb; | 4230 | from = pmbx; |
| 2743 | from += sizeof(MAILBOX_t); | 4231 | ext = from + sizeof(MAILBOX_t); |
| 2744 | memcpy((uint8_t *)ext, from, | ||
| 2745 | mbox_req->inExtWLen * sizeof(uint32_t)); | ||
| 2746 | } | 4232 | } |
| 2747 | |||
| 2748 | pmboxq->context2 = ext; | 4233 | pmboxq->context2 = ext; |
| 2749 | pmboxq->in_ext_byte_len = | 4234 | pmboxq->in_ext_byte_len = |
| 2750 | mbox_req->inExtWLen * sizeof(uint32_t); | 4235 | mbox_req->inExtWLen * sizeof(uint32_t); |
| @@ -2768,46 +4253,17 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2768 | rc = -ERANGE; | 4253 | rc = -ERANGE; |
| 2769 | goto job_done; | 4254 | goto job_done; |
| 2770 | } | 4255 | } |
| 2771 | |||
| 2772 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
| 2773 | if (!rxbmp) { | ||
| 2774 | rc = -ENOMEM; | ||
| 2775 | goto job_done; | ||
| 2776 | } | ||
| 2777 | |||
| 2778 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
| 2779 | if (!rxbmp->virt) { | ||
| 2780 | rc = -ENOMEM; | ||
| 2781 | goto job_done; | ||
| 2782 | } | ||
| 2783 | |||
| 2784 | INIT_LIST_HEAD(&rxbmp->list); | ||
| 2785 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
| 2786 | dmp = diag_cmd_data_alloc(phba, rxbpl, transmit_length, 0); | ||
| 2787 | if (!dmp) { | ||
| 2788 | rc = -ENOMEM; | ||
| 2789 | goto job_done; | ||
| 2790 | } | ||
| 2791 | |||
| 2792 | INIT_LIST_HEAD(&dmp->dma.list); | ||
| 2793 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = | 4256 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = |
| 2794 | putPaddrHigh(dmp->dma.phys); | 4257 | putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t)); |
| 2795 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = | 4258 | pmb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = |
| 2796 | putPaddrLow(dmp->dma.phys); | 4259 | putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t)); |
| 2797 | 4260 | ||
| 2798 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = | 4261 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = |
| 2799 | putPaddrHigh(dmp->dma.phys + | 4262 | putPaddrHigh(dmabuf->phys + sizeof(MAILBOX_t) |
| 2800 | pmb->un.varBIUdiag.un.s2. | 4263 | + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize); |
| 2801 | xmit_bde64.tus.f.bdeSize); | ||
| 2802 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = | 4264 | pmb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = |
| 2803 | putPaddrLow(dmp->dma.phys + | 4265 | putPaddrLow(dmabuf->phys + sizeof(MAILBOX_t) |
| 2804 | pmb->un.varBIUdiag.un.s2. | 4266 | + pmb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize); |
| 2805 | xmit_bde64.tus.f.bdeSize); | ||
| 2806 | |||
| 2807 | /* copy the transmit data found in the mailbox extension area */ | ||
| 2808 | from = (uint8_t *)mb; | ||
| 2809 | from += sizeof(MAILBOX_t); | ||
| 2810 | memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); | ||
| 2811 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { | 4267 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { |
| 2812 | rdEventLog = &pmb->un.varRdEventLog; | 4268 | rdEventLog = &pmb->un.varRdEventLog; |
| 2813 | receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; | 4269 | receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; |
| @@ -2823,33 +4279,10 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2823 | 4279 | ||
| 2824 | /* mode zero uses a bde like biu diags command */ | 4280 | /* mode zero uses a bde like biu diags command */ |
| 2825 | if (mode == 0) { | 4281 | if (mode == 0) { |
| 2826 | 4282 | pmb->un.varWords[3] = putPaddrLow(dmabuf->phys | |
| 2827 | /* rebuild the command for sli4 using our own buffers | 4283 | + sizeof(MAILBOX_t)); |
| 2828 | * like we do for biu diags | 4284 | pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys |
| 2829 | */ | 4285 | + sizeof(MAILBOX_t)); |
| 2830 | |||
| 2831 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
| 2832 | if (!rxbmp) { | ||
| 2833 | rc = -ENOMEM; | ||
| 2834 | goto job_done; | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
| 2838 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
| 2839 | if (rxbpl) { | ||
| 2840 | INIT_LIST_HEAD(&rxbmp->list); | ||
| 2841 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
| 2842 | receive_length, 0); | ||
| 2843 | } | ||
| 2844 | |||
| 2845 | if (!dmp) { | ||
| 2846 | rc = -ENOMEM; | ||
| 2847 | goto job_done; | ||
| 2848 | } | ||
| 2849 | |||
| 2850 | INIT_LIST_HEAD(&dmp->dma.list); | ||
| 2851 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
| 2852 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
| 2853 | } | 4286 | } |
| 2854 | } else if (phba->sli_rev == LPFC_SLI_REV4) { | 4287 | } else if (phba->sli_rev == LPFC_SLI_REV4) { |
| 2855 | if (pmb->mbxCommand == MBX_DUMP_MEMORY) { | 4288 | if (pmb->mbxCommand == MBX_DUMP_MEMORY) { |
| @@ -2860,36 +4293,14 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2860 | /* receive length cannot be greater than mailbox | 4293 | /* receive length cannot be greater than mailbox |
| 2861 | * extension size | 4294 | * extension size |
| 2862 | */ | 4295 | */ |
| 2863 | if ((receive_length == 0) || | 4296 | if (receive_length == 0) { |
| 2864 | (receive_length > MAILBOX_EXT_SIZE)) { | ||
| 2865 | rc = -ERANGE; | 4297 | rc = -ERANGE; |
| 2866 | goto job_done; | 4298 | goto job_done; |
| 2867 | } | 4299 | } |
| 2868 | 4300 | pmb->un.varWords[3] = putPaddrLow(dmabuf->phys | |
| 2869 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4301 | + sizeof(MAILBOX_t)); |
| 2870 | if (!rxbmp) { | 4302 | pmb->un.varWords[4] = putPaddrHigh(dmabuf->phys |
| 2871 | rc = -ENOMEM; | 4303 | + sizeof(MAILBOX_t)); |
| 2872 | goto job_done; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
| 2876 | if (!rxbmp->virt) { | ||
| 2877 | rc = -ENOMEM; | ||
| 2878 | goto job_done; | ||
| 2879 | } | ||
| 2880 | |||
| 2881 | INIT_LIST_HEAD(&rxbmp->list); | ||
| 2882 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
| 2883 | dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, | ||
| 2884 | 0); | ||
| 2885 | if (!dmp) { | ||
| 2886 | rc = -ENOMEM; | ||
| 2887 | goto job_done; | ||
| 2888 | } | ||
| 2889 | |||
| 2890 | INIT_LIST_HEAD(&dmp->dma.list); | ||
| 2891 | pmb->un.varWords[3] = putPaddrLow(dmp->dma.phys); | ||
| 2892 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | ||
| 2893 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && | 4304 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && |
| 2894 | pmb->un.varUpdateCfg.co) { | 4305 | pmb->un.varUpdateCfg.co) { |
| 2895 | bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; | 4306 | bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; |
| @@ -2899,102 +4310,53 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 2899 | rc = -ERANGE; | 4310 | rc = -ERANGE; |
| 2900 | goto job_done; | 4311 | goto job_done; |
| 2901 | } | 4312 | } |
| 2902 | 4313 | bde->addrHigh = putPaddrHigh(dmabuf->phys | |
| 2903 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4314 | + sizeof(MAILBOX_t)); |
| 2904 | if (!rxbmp) { | 4315 | bde->addrLow = putPaddrLow(dmabuf->phys |
| 2905 | rc = -ENOMEM; | 4316 | + sizeof(MAILBOX_t)); |
| 2906 | goto job_done; | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
| 2910 | if (!rxbmp->virt) { | ||
| 2911 | rc = -ENOMEM; | ||
| 2912 | goto job_done; | ||
| 2913 | } | ||
| 2914 | |||
| 2915 | INIT_LIST_HEAD(&rxbmp->list); | ||
| 2916 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | ||
| 2917 | dmp = diag_cmd_data_alloc(phba, rxbpl, | ||
| 2918 | bde->tus.f.bdeSize, 0); | ||
| 2919 | if (!dmp) { | ||
| 2920 | rc = -ENOMEM; | ||
| 2921 | goto job_done; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | INIT_LIST_HEAD(&dmp->dma.list); | ||
| 2925 | bde->addrHigh = putPaddrHigh(dmp->dma.phys); | ||
| 2926 | bde->addrLow = putPaddrLow(dmp->dma.phys); | ||
| 2927 | |||
| 2928 | /* copy the transmit data found in the mailbox | ||
| 2929 | * extension area | ||
| 2930 | */ | ||
| 2931 | from = (uint8_t *)mb; | ||
| 2932 | from += sizeof(MAILBOX_t); | ||
| 2933 | memcpy((uint8_t *)dmp->dma.virt, from, | ||
| 2934 | bde->tus.f.bdeSize); | ||
| 2935 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { | 4317 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { |
| 2936 | /* rebuild the command for sli4 using our own buffers | 4318 | /* Handling non-embedded SLI_CONFIG mailbox command */ |
| 2937 | * like we do for biu diags | 4319 | sli4_config = &pmboxq->u.mqe.un.sli4_config; |
| 2938 | */ | 4320 | if (!bf_get(lpfc_mbox_hdr_emb, |
| 2939 | header = (struct mbox_header *)&pmb->un.varWords[0]; | 4321 | &sli4_config->header.cfg_mhdr)) { |
| 2940 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | 4322 | /* rebuild the command for sli4 using our |
| 2941 | &pmb->un.varWords[0]; | 4323 | * own buffers like we do for biu diags |
| 2942 | receive_length = nembed_sge->sge[0].length; | 4324 | */ |
| 2943 | 4325 | header = (struct mbox_header *) | |
| 2944 | /* receive length cannot be greater than mailbox | 4326 | &pmb->un.varWords[0]; |
| 2945 | * extension size | 4327 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) |
| 2946 | */ | 4328 | &pmb->un.varWords[0]; |
| 2947 | if ((receive_length == 0) || | 4329 | receive_length = nembed_sge->sge[0].length; |
| 2948 | (receive_length > MAILBOX_EXT_SIZE)) { | 4330 | |
| 2949 | rc = -ERANGE; | 4331 | /* receive length cannot be greater than |
| 2950 | goto job_done; | 4332 | * mailbox extension size |
| 2951 | } | 4333 | */ |
| 2952 | 4334 | if ((receive_length == 0) || | |
| 2953 | rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 4335 | (receive_length > MAILBOX_EXT_SIZE)) { |
| 2954 | if (!rxbmp) { | 4336 | rc = -ERANGE; |
| 2955 | rc = -ENOMEM; | 4337 | goto job_done; |
| 2956 | goto job_done; | 4338 | } |
| 2957 | } | ||
| 2958 | |||
| 2959 | rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys); | ||
| 2960 | if (!rxbmp->virt) { | ||
| 2961 | rc = -ENOMEM; | ||
| 2962 | goto job_done; | ||
| 2963 | } | ||
| 2964 | 4339 | ||
| 2965 | INIT_LIST_HEAD(&rxbmp->list); | 4340 | nembed_sge->sge[0].pa_hi = |
| 2966 | rxbpl = (struct ulp_bde64 *) rxbmp->virt; | 4341 | putPaddrHigh(dmabuf->phys |
| 2967 | dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length, | 4342 | + sizeof(MAILBOX_t)); |
| 2968 | 0); | 4343 | nembed_sge->sge[0].pa_lo = |
| 2969 | if (!dmp) { | 4344 | putPaddrLow(dmabuf->phys |
| 2970 | rc = -ENOMEM; | 4345 | + sizeof(MAILBOX_t)); |
| 2971 | goto job_done; | ||
| 2972 | } | 4346 | } |
| 2973 | |||
| 2974 | INIT_LIST_HEAD(&dmp->dma.list); | ||
| 2975 | nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys); | ||
| 2976 | nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys); | ||
| 2977 | /* copy the transmit data found in the mailbox | ||
| 2978 | * extension area | ||
| 2979 | */ | ||
| 2980 | from = (uint8_t *)mb; | ||
| 2981 | from += sizeof(MAILBOX_t); | ||
| 2982 | memcpy((uint8_t *)dmp->dma.virt, from, | ||
| 2983 | header->cfg_mhdr.payload_length); | ||
| 2984 | } | 4347 | } |
| 2985 | } | 4348 | } |
| 2986 | 4349 | ||
| 2987 | dd_data->context_un.mbox.rxbmp = rxbmp; | 4350 | dd_data->context_un.mbox.dmabuffers = dmabuf; |
| 2988 | dd_data->context_un.mbox.dmp = dmp; | ||
| 2989 | 4351 | ||
| 2990 | /* setup wake call as IOCB callback */ | 4352 | /* setup wake call as IOCB callback */ |
| 2991 | pmboxq->mbox_cmpl = lpfc_bsg_wake_mbox_wait; | 4353 | pmboxq->mbox_cmpl = lpfc_bsg_issue_mbox_cmpl; |
| 2992 | 4354 | ||
| 2993 | /* setup context field to pass wait_queue pointer to wake function */ | 4355 | /* setup context field to pass wait_queue pointer to wake function */ |
| 2994 | pmboxq->context1 = dd_data; | 4356 | pmboxq->context1 = dd_data; |
| 2995 | dd_data->type = TYPE_MBOX; | 4357 | dd_data->type = TYPE_MBOX; |
| 2996 | dd_data->context_un.mbox.pmboxq = pmboxq; | 4358 | dd_data->context_un.mbox.pmboxq = pmboxq; |
| 2997 | dd_data->context_un.mbox.mb = mb; | 4359 | dd_data->context_un.mbox.mb = (MAILBOX_t *)pmbx; |
| 2998 | dd_data->context_un.mbox.set_job = job; | 4360 | dd_data->context_un.mbox.set_job = job; |
| 2999 | dd_data->context_un.mbox.ext = ext; | 4361 | dd_data->context_un.mbox.ext = ext; |
| 3000 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; | 4362 | dd_data->context_un.mbox.mbOffset = mbox_req->mbOffset; |
| @@ -3011,11 +4373,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 3011 | } | 4373 | } |
| 3012 | 4374 | ||
| 3013 | /* job finished, copy the data */ | 4375 | /* job finished, copy the data */ |
| 3014 | memcpy(mb, pmb, sizeof(*pmb)); | 4376 | memcpy(pmbx, pmb, sizeof(*pmb)); |
| 3015 | job->reply->reply_payload_rcv_len = | 4377 | job->reply->reply_payload_rcv_len = |
| 3016 | sg_copy_from_buffer(job->reply_payload.sg_list, | 4378 | sg_copy_from_buffer(job->reply_payload.sg_list, |
| 3017 | job->reply_payload.sg_cnt, | 4379 | job->reply_payload.sg_cnt, |
| 3018 | mb, size); | 4380 | pmbx, size); |
| 3019 | /* not waiting mbox already done */ | 4381 | /* not waiting mbox already done */ |
| 3020 | rc = 0; | 4382 | rc = 0; |
| 3021 | goto job_done; | 4383 | goto job_done; |
| @@ -3027,22 +4389,12 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
| 3027 | 4389 | ||
| 3028 | job_done: | 4390 | job_done: |
| 3029 | /* common exit for error or job completed inline */ | 4391 | /* common exit for error or job completed inline */ |
| 3030 | kfree(mb); | ||
| 3031 | if (pmboxq) | 4392 | if (pmboxq) |
| 3032 | mempool_free(pmboxq, phba->mbox_mem_pool); | 4393 | mempool_free(pmboxq, phba->mbox_mem_pool); |
| 3033 | kfree(ext); | 4394 | lpfc_bsg_dma_page_free(phba, dmabuf); |
| 3034 | if (dmp) { | ||
| 3035 | dma_free_coherent(&phba->pcidev->dev, | ||
| 3036 | dmp->size, dmp->dma.virt, | ||
| 3037 | dmp->dma.phys); | ||
| 3038 | kfree(dmp); | ||
| 3039 | } | ||
| 3040 | if (rxbmp) { | ||
| 3041 | lpfc_mbuf_free(phba, rxbmp->virt, rxbmp->phys); | ||
| 3042 | kfree(rxbmp); | ||
| 3043 | } | ||
| 3044 | kfree(dd_data); | 4395 | kfree(dd_data); |
| 3045 | 4396 | ||
| 4397 | job_cont: | ||
| 3046 | return rc; | 4398 | return rc; |
| 3047 | } | 4399 | } |
| 3048 | 4400 | ||
| @@ -3055,37 +4407,28 @@ lpfc_bsg_mbox_cmd(struct fc_bsg_job *job) | |||
| 3055 | { | 4407 | { |
| 3056 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; | 4408 | struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata; |
| 3057 | struct lpfc_hba *phba = vport->phba; | 4409 | struct lpfc_hba *phba = vport->phba; |
| 4410 | struct dfc_mbox_req *mbox_req; | ||
| 3058 | int rc = 0; | 4411 | int rc = 0; |
| 3059 | 4412 | ||
| 3060 | /* in case no data is transferred */ | 4413 | /* mix-and-match backward compatibility */ |
| 3061 | job->reply->reply_payload_rcv_len = 0; | 4414 | job->reply->reply_payload_rcv_len = 0; |
| 3062 | if (job->request_len < | 4415 | if (job->request_len < |
| 3063 | sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { | 4416 | sizeof(struct fc_bsg_request) + sizeof(struct dfc_mbox_req)) { |
| 3064 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | 4417 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, |
| 3065 | "2737 Received MBOX_REQ request below " | 4418 | "2737 Mix-and-match backward compability " |
| 3066 | "minimum size\n"); | 4419 | "between MBOX_REQ old size:%d and " |
| 3067 | rc = -EINVAL; | 4420 | "new request size:%d\n", |
| 3068 | goto job_error; | 4421 | (int)(job->request_len - |
| 3069 | } | 4422 | sizeof(struct fc_bsg_request)), |
| 3070 | 4423 | (int)sizeof(struct dfc_mbox_req)); | |
| 3071 | if (job->request_payload.payload_len != BSG_MBOX_SIZE) { | 4424 | mbox_req = (struct dfc_mbox_req *) |
| 3072 | rc = -EINVAL; | 4425 | job->request->rqst_data.h_vendor.vendor_cmd; |
| 3073 | goto job_error; | 4426 | mbox_req->extMboxTag = 0; |
| 3074 | } | 4427 | mbox_req->extSeqNum = 0; |
| 3075 | |||
| 3076 | if (job->reply_payload.payload_len != BSG_MBOX_SIZE) { | ||
| 3077 | rc = -EINVAL; | ||
| 3078 | goto job_error; | ||
| 3079 | } | ||
| 3080 | |||
| 3081 | if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { | ||
| 3082 | rc = -EAGAIN; | ||
| 3083 | goto job_error; | ||
| 3084 | } | 4428 | } |
| 3085 | 4429 | ||
| 3086 | rc = lpfc_bsg_issue_mbox(phba, job, vport); | 4430 | rc = lpfc_bsg_issue_mbox(phba, job, vport); |
| 3087 | 4431 | ||
| 3088 | job_error: | ||
| 3089 | if (rc == 0) { | 4432 | if (rc == 0) { |
| 3090 | /* job done */ | 4433 | /* job done */ |
| 3091 | job->reply->result = 0; | 4434 | job->reply->result = 0; |
| @@ -3416,10 +4759,16 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job) | |||
| 3416 | rc = lpfc_bsg_send_mgmt_rsp(job); | 4759 | rc = lpfc_bsg_send_mgmt_rsp(job); |
| 3417 | break; | 4760 | break; |
| 3418 | case LPFC_BSG_VENDOR_DIAG_MODE: | 4761 | case LPFC_BSG_VENDOR_DIAG_MODE: |
| 3419 | rc = lpfc_bsg_diag_mode(job); | 4762 | rc = lpfc_bsg_diag_loopback_mode(job); |
| 4763 | break; | ||
| 4764 | case LPFC_BSG_VENDOR_DIAG_MODE_END: | ||
| 4765 | rc = lpfc_sli4_bsg_diag_mode_end(job); | ||
| 4766 | break; | ||
| 4767 | case LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK: | ||
| 4768 | rc = lpfc_bsg_diag_loopback_run(job); | ||
| 3420 | break; | 4769 | break; |
| 3421 | case LPFC_BSG_VENDOR_DIAG_TEST: | 4770 | case LPFC_BSG_VENDOR_LINK_DIAG_TEST: |
| 3422 | rc = lpfc_bsg_diag_test(job); | 4771 | rc = lpfc_sli4_bsg_link_diag_test(job); |
| 3423 | break; | 4772 | break; |
| 3424 | case LPFC_BSG_VENDOR_GET_MGMT_REV: | 4773 | case LPFC_BSG_VENDOR_GET_MGMT_REV: |
| 3425 | rc = lpfc_bsg_get_dfc_rev(job); | 4774 | rc = lpfc_bsg_get_dfc_rev(job); |
| @@ -3538,6 +4887,8 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
| 3538 | /* the mbox completion handler can now be run */ | 4887 | /* the mbox completion handler can now be run */ |
| 3539 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 4888 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
| 3540 | job->job_done(job); | 4889 | job->job_done(job); |
| 4890 | if (phba->mbox_ext_buf_ctx.state == LPFC_BSG_MBOX_PORT) | ||
| 4891 | phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS; | ||
| 3541 | break; | 4892 | break; |
| 3542 | case TYPE_MENLO: | 4893 | case TYPE_MENLO: |
| 3543 | menlo = &dd_data->context_un.menlo; | 4894 | menlo = &dd_data->context_un.menlo; |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index b542aca6f5ae..c8c2b47ea886 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h | |||
| @@ -24,15 +24,17 @@ | |||
| 24 | * These are the vendor unique structures passed in using the bsg | 24 | * These are the vendor unique structures passed in using the bsg |
| 25 | * FC_BSG_HST_VENDOR message code type. | 25 | * FC_BSG_HST_VENDOR message code type. |
| 26 | */ | 26 | */ |
| 27 | #define LPFC_BSG_VENDOR_SET_CT_EVENT 1 | 27 | #define LPFC_BSG_VENDOR_SET_CT_EVENT 1 |
| 28 | #define LPFC_BSG_VENDOR_GET_CT_EVENT 2 | 28 | #define LPFC_BSG_VENDOR_GET_CT_EVENT 2 |
| 29 | #define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3 | 29 | #define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3 |
| 30 | #define LPFC_BSG_VENDOR_DIAG_MODE 4 | 30 | #define LPFC_BSG_VENDOR_DIAG_MODE 4 |
| 31 | #define LPFC_BSG_VENDOR_DIAG_TEST 5 | 31 | #define LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK 5 |
| 32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 | 32 | #define LPFC_BSG_VENDOR_GET_MGMT_REV 6 |
| 33 | #define LPFC_BSG_VENDOR_MBOX 7 | 33 | #define LPFC_BSG_VENDOR_MBOX 7 |
| 34 | #define LPFC_BSG_VENDOR_MENLO_CMD 8 | 34 | #define LPFC_BSG_VENDOR_MENLO_CMD 8 |
| 35 | #define LPFC_BSG_VENDOR_MENLO_DATA 9 | 35 | #define LPFC_BSG_VENDOR_MENLO_DATA 9 |
| 36 | #define LPFC_BSG_VENDOR_DIAG_MODE_END 10 | ||
| 37 | #define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11 | ||
| 36 | 38 | ||
| 37 | struct set_ct_event { | 39 | struct set_ct_event { |
| 38 | uint32_t command; | 40 | uint32_t command; |
| @@ -67,10 +69,25 @@ struct diag_mode_set { | |||
| 67 | uint32_t timeout; | 69 | uint32_t timeout; |
| 68 | }; | 70 | }; |
| 69 | 71 | ||
| 72 | struct sli4_link_diag { | ||
| 73 | uint32_t command; | ||
| 74 | uint32_t timeout; | ||
| 75 | uint32_t test_id; | ||
| 76 | uint32_t loops; | ||
| 77 | uint32_t test_version; | ||
| 78 | uint32_t error_action; | ||
| 79 | }; | ||
| 80 | |||
| 70 | struct diag_mode_test { | 81 | struct diag_mode_test { |
| 71 | uint32_t command; | 82 | uint32_t command; |
| 72 | }; | 83 | }; |
| 73 | 84 | ||
| 85 | struct diag_status { | ||
| 86 | uint32_t mbox_status; | ||
| 87 | uint32_t shdr_status; | ||
| 88 | uint32_t shdr_add_status; | ||
| 89 | }; | ||
| 90 | |||
| 74 | #define LPFC_WWNN_TYPE 0 | 91 | #define LPFC_WWNN_TYPE 0 |
| 75 | #define LPFC_WWPN_TYPE 1 | 92 | #define LPFC_WWPN_TYPE 1 |
| 76 | 93 | ||
| @@ -92,11 +109,15 @@ struct get_mgmt_rev_reply { | |||
| 92 | }; | 109 | }; |
| 93 | 110 | ||
| 94 | #define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */ | 111 | #define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */ |
| 112 | |||
| 113 | /* BSG mailbox request header */ | ||
| 95 | struct dfc_mbox_req { | 114 | struct dfc_mbox_req { |
| 96 | uint32_t command; | 115 | uint32_t command; |
| 97 | uint32_t mbOffset; | 116 | uint32_t mbOffset; |
| 98 | uint32_t inExtWLen; | 117 | uint32_t inExtWLen; |
| 99 | uint32_t outExtWLen; | 118 | uint32_t outExtWLen; |
| 119 | uint32_t extMboxTag; | ||
| 120 | uint32_t extSeqNum; | ||
| 100 | }; | 121 | }; |
| 101 | 122 | ||
| 102 | /* Used for menlo command or menlo data. The xri is only used for menlo data */ | 123 | /* Used for menlo command or menlo data. The xri is only used for menlo data */ |
| @@ -171,7 +192,7 @@ struct lpfc_sli_config_mse { | |||
| 171 | #define lpfc_mbox_sli_config_mse_len_WORD buf_len | 192 | #define lpfc_mbox_sli_config_mse_len_WORD buf_len |
| 172 | }; | 193 | }; |
| 173 | 194 | ||
| 174 | struct lpfc_sli_config_subcmd_hbd { | 195 | struct lpfc_sli_config_hbd { |
| 175 | uint32_t buf_len; | 196 | uint32_t buf_len; |
| 176 | #define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 | 197 | #define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 |
| 177 | #define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff | 198 | #define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff |
| @@ -194,21 +215,39 @@ struct lpfc_sli_config_hdr { | |||
| 194 | uint32_t reserved5; | 215 | uint32_t reserved5; |
| 195 | }; | 216 | }; |
| 196 | 217 | ||
| 197 | struct lpfc_sli_config_generic { | 218 | struct lpfc_sli_config_emb0_subsys { |
| 198 | struct lpfc_sli_config_hdr sli_config_hdr; | 219 | struct lpfc_sli_config_hdr sli_config_hdr; |
| 199 | #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 | 220 | #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 |
| 200 | struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; | 221 | struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; |
| 222 | uint32_t padding; | ||
| 223 | uint32_t word64; | ||
| 224 | #define lpfc_emb0_subcmnd_opcode_SHIFT 0 | ||
| 225 | #define lpfc_emb0_subcmnd_opcode_MASK 0xff | ||
| 226 | #define lpfc_emb0_subcmnd_opcode_WORD word64 | ||
| 227 | #define lpfc_emb0_subcmnd_subsys_SHIFT 8 | ||
| 228 | #define lpfc_emb0_subcmnd_subsys_MASK 0xff | ||
| 229 | #define lpfc_emb0_subcmnd_subsys_WORD word64 | ||
| 230 | /* Subsystem FCOE (0x0C) OpCodes */ | ||
| 231 | #define SLI_CONFIG_SUBSYS_FCOE 0x0C | ||
| 232 | #define FCOE_OPCODE_READ_FCF 0x08 | ||
| 233 | #define FCOE_OPCODE_ADD_FCF 0x09 | ||
| 201 | }; | 234 | }; |
| 202 | 235 | ||
| 203 | struct lpfc_sli_config_subcmnd { | 236 | struct lpfc_sli_config_emb1_subsys { |
| 204 | struct lpfc_sli_config_hdr sli_config_hdr; | 237 | struct lpfc_sli_config_hdr sli_config_hdr; |
| 205 | uint32_t word6; | 238 | uint32_t word6; |
| 206 | #define lpfc_subcmnd_opcode_SHIFT 0 | 239 | #define lpfc_emb1_subcmnd_opcode_SHIFT 0 |
| 207 | #define lpfc_subcmnd_opcode_MASK 0xff | 240 | #define lpfc_emb1_subcmnd_opcode_MASK 0xff |
| 208 | #define lpfc_subcmnd_opcode_WORD word6 | 241 | #define lpfc_emb1_subcmnd_opcode_WORD word6 |
| 209 | #define lpfc_subcmnd_subsys_SHIFT 8 | 242 | #define lpfc_emb1_subcmnd_subsys_SHIFT 8 |
| 210 | #define lpfc_subcmnd_subsys_MASK 0xff | 243 | #define lpfc_emb1_subcmnd_subsys_MASK 0xff |
| 211 | #define lpfc_subcmnd_subsys_WORD word6 | 244 | #define lpfc_emb1_subcmnd_subsys_WORD word6 |
| 245 | /* Subsystem COMN (0x01) OpCodes */ | ||
| 246 | #define SLI_CONFIG_SUBSYS_COMN 0x01 | ||
| 247 | #define COMN_OPCODE_READ_OBJECT 0xAB | ||
| 248 | #define COMN_OPCODE_WRITE_OBJECT 0xAC | ||
| 249 | #define COMN_OPCODE_READ_OBJECT_LIST 0xAD | ||
| 250 | #define COMN_OPCODE_DELETE_OBJECT 0xAE | ||
| 212 | uint32_t timeout; | 251 | uint32_t timeout; |
| 213 | uint32_t request_length; | 252 | uint32_t request_length; |
| 214 | uint32_t word9; | 253 | uint32_t word9; |
| @@ -222,8 +261,8 @@ struct lpfc_sli_config_subcmnd { | |||
| 222 | uint32_t rd_offset; | 261 | uint32_t rd_offset; |
| 223 | uint32_t obj_name[26]; | 262 | uint32_t obj_name[26]; |
| 224 | uint32_t hbd_count; | 263 | uint32_t hbd_count; |
| 225 | #define LPFC_MBX_SLI_CONFIG_MAX_HBD 10 | 264 | #define LPFC_MBX_SLI_CONFIG_MAX_HBD 8 |
| 226 | struct lpfc_sli_config_subcmd_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; | 265 | struct lpfc_sli_config_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; |
| 227 | }; | 266 | }; |
| 228 | 267 | ||
| 229 | struct lpfc_sli_config_mbox { | 268 | struct lpfc_sli_config_mbox { |
| @@ -235,7 +274,11 @@ struct lpfc_sli_config_mbox { | |||
| 235 | #define lpfc_mqe_command_MASK 0x000000FF | 274 | #define lpfc_mqe_command_MASK 0x000000FF |
| 236 | #define lpfc_mqe_command_WORD word0 | 275 | #define lpfc_mqe_command_WORD word0 |
| 237 | union { | 276 | union { |
| 238 | struct lpfc_sli_config_generic sli_config_generic; | 277 | struct lpfc_sli_config_emb0_subsys sli_config_emb0_subsys; |
| 239 | struct lpfc_sli_config_subcmnd sli_config_subcmnd; | 278 | struct lpfc_sli_config_emb1_subsys sli_config_emb1_subsys; |
| 240 | } un; | 279 | } un; |
| 241 | }; | 280 | }; |
| 281 | |||
| 282 | /* driver only */ | ||
| 283 | #define SLI_CONFIG_NOT_HANDLED 0 | ||
| 284 | #define SLI_CONFIG_HANDLED 1 | ||
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f0b332f4eedb..fc20c247f36b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -55,6 +55,8 @@ void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); | |||
| 55 | void lpfc_supported_pages(struct lpfcMboxq *); | 55 | void lpfc_supported_pages(struct lpfcMboxq *); |
| 56 | void lpfc_pc_sli4_params(struct lpfcMboxq *); | 56 | void lpfc_pc_sli4_params(struct lpfcMboxq *); |
| 57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); | 57 | int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 58 | int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *, | ||
| 59 | uint16_t, uint16_t, bool); | ||
| 58 | int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *); | 60 | int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 59 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); | 61 | struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); |
| 60 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); | 62 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); |
| @@ -171,6 +173,7 @@ void lpfc_delayed_disc_tmo(unsigned long); | |||
| 171 | void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); | 173 | void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); |
| 172 | 174 | ||
| 173 | int lpfc_config_port_prep(struct lpfc_hba *); | 175 | int lpfc_config_port_prep(struct lpfc_hba *); |
| 176 | void lpfc_update_vport_wwn(struct lpfc_vport *vport); | ||
| 174 | int lpfc_config_port_post(struct lpfc_hba *); | 177 | int lpfc_config_port_post(struct lpfc_hba *); |
| 175 | int lpfc_hba_down_prep(struct lpfc_hba *); | 178 | int lpfc_hba_down_prep(struct lpfc_hba *); |
| 176 | int lpfc_hba_down_post(struct lpfc_hba *); | 179 | int lpfc_hba_down_post(struct lpfc_hba *); |
| @@ -365,6 +368,10 @@ extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, uint32_t, | |||
| 365 | uint32_t, uint32_t); | 368 | uint32_t, uint32_t); |
| 366 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | 369 | extern struct lpfc_hbq_init *lpfc_hbq_defs[]; |
| 367 | 370 | ||
| 371 | /* SLI4 if_type 2 externs. */ | ||
| 372 | int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *); | ||
| 373 | int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *); | ||
| 374 | |||
| 368 | /* externs BlockGuard */ | 375 | /* externs BlockGuard */ |
| 369 | extern char *_dump_buf_data; | 376 | extern char *_dump_buf_data; |
| 370 | extern unsigned long _dump_buf_data_order; | 377 | extern unsigned long _dump_buf_data_order; |
| @@ -429,3 +436,6 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | |||
| 429 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); | 436 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); |
| 430 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | 437 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, |
| 431 | uint32_t); | 438 | uint32_t); |
| 439 | int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); | ||
| 440 | /* functions to support SR-IOV */ | ||
| 441 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); | ||
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index d9edfd90d7ff..779b88e1469d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
| @@ -352,6 +352,8 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
| 352 | icmd->ulpLe = 1; | 352 | icmd->ulpLe = 1; |
| 353 | icmd->ulpClass = CLASS3; | 353 | icmd->ulpClass = CLASS3; |
| 354 | icmd->ulpContext = ndlp->nlp_rpi; | 354 | icmd->ulpContext = ndlp->nlp_rpi; |
| 355 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 356 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
| 355 | 357 | ||
| 356 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 358 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
| 357 | /* For GEN_REQUEST64_CR, use the RPI */ | 359 | /* For GEN_REQUEST64_CR, use the RPI */ |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index c93fca058603..ffe82d169b40 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
| @@ -1665,7 +1665,8 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
| 1665 | /* Get fast-path complete queue information */ | 1665 | /* Get fast-path complete queue information */ |
| 1666 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1666 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
| 1667 | "Fast-path FCP CQ information:\n"); | 1667 | "Fast-path FCP CQ information:\n"); |
| 1668 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | 1668 | fcp_qidx = 0; |
| 1669 | do { | ||
| 1669 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1670 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
| 1670 | "Associated EQID[%02d]:\n", | 1671 | "Associated EQID[%02d]:\n", |
| 1671 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); | 1672 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); |
| @@ -1678,7 +1679,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
| 1678 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, | 1679 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, |
| 1679 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | 1680 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, |
| 1680 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | 1681 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); |
| 1681 | } | 1682 | } while (++fcp_qidx < phba->cfg_fcp_eq_count); |
| 1682 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | 1683 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); |
| 1683 | 1684 | ||
| 1684 | /* Get mailbox queue information */ | 1685 | /* Get mailbox queue information */ |
| @@ -2012,7 +2013,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | |||
| 2012 | goto pass_check; | 2013 | goto pass_check; |
| 2013 | } | 2014 | } |
| 2014 | /* FCP complete queue */ | 2015 | /* FCP complete queue */ |
| 2015 | for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { | 2016 | qidx = 0; |
| 2017 | do { | ||
| 2016 | if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { | 2018 | if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { |
| 2017 | /* Sanity check */ | 2019 | /* Sanity check */ |
| 2018 | rc = lpfc_idiag_que_param_check( | 2020 | rc = lpfc_idiag_que_param_check( |
| @@ -2024,7 +2026,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | |||
| 2024 | phba->sli4_hba.fcp_cq[qidx]; | 2026 | phba->sli4_hba.fcp_cq[qidx]; |
| 2025 | goto pass_check; | 2027 | goto pass_check; |
| 2026 | } | 2028 | } |
| 2027 | } | 2029 | } while (++qidx < phba->cfg_fcp_eq_count); |
| 2028 | goto error_out; | 2030 | goto error_out; |
| 2029 | break; | 2031 | break; |
| 2030 | case LPFC_IDIAG_MQ: | 2032 | case LPFC_IDIAG_MQ: |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index e2c452467c8b..32a084534f3e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -250,7 +250,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
| 250 | icmd->un.elsreq64.myID = vport->fc_myDID; | 250 | icmd->un.elsreq64.myID = vport->fc_myDID; |
| 251 | 251 | ||
| 252 | /* For ELS_REQUEST64_CR, use the VPI by default */ | 252 | /* For ELS_REQUEST64_CR, use the VPI by default */ |
| 253 | icmd->ulpContext = vport->vpi + phba->vpi_base; | 253 | icmd->ulpContext = phba->vpi_ids[vport->vpi]; |
| 254 | icmd->ulpCt_h = 0; | 254 | icmd->ulpCt_h = 0; |
| 255 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ | 255 | /* The CT field must be 0=INVALID_RPI for the ECHO cmd */ |
| 256 | if (elscmd == ELS_CMD_ECHO) | 256 | if (elscmd == ELS_CMD_ECHO) |
| @@ -454,6 +454,7 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) | |||
| 454 | rc = -ENOMEM; | 454 | rc = -ENOMEM; |
| 455 | goto fail_free_dmabuf; | 455 | goto fail_free_dmabuf; |
| 456 | } | 456 | } |
| 457 | |||
| 457 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 458 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 458 | if (!mboxq) { | 459 | if (!mboxq) { |
| 459 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
| @@ -6585,6 +6586,26 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) | |||
| 6585 | { | 6586 | { |
| 6586 | struct lpfc_vport *vport; | 6587 | struct lpfc_vport *vport; |
| 6587 | unsigned long flags; | 6588 | unsigned long flags; |
| 6589 | int i; | ||
| 6590 | |||
| 6591 | /* The physical ports are always vpi 0 - translate is unnecessary. */ | ||
| 6592 | if (vpi > 0) { | ||
| 6593 | /* | ||
| 6594 | * Translate the physical vpi to the logical vpi. The | ||
| 6595 | * vport stores the logical vpi. | ||
| 6596 | */ | ||
| 6597 | for (i = 0; i < phba->max_vpi; i++) { | ||
| 6598 | if (vpi == phba->vpi_ids[i]) | ||
| 6599 | break; | ||
| 6600 | } | ||
| 6601 | |||
| 6602 | if (i >= phba->max_vpi) { | ||
| 6603 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
| 6604 | "2936 Could not find Vport mapped " | ||
| 6605 | "to vpi %d\n", vpi); | ||
| 6606 | return NULL; | ||
| 6607 | } | ||
| 6608 | } | ||
| 6588 | 6609 | ||
| 6589 | spin_lock_irqsave(&phba->hbalock, flags); | 6610 | spin_lock_irqsave(&phba->hbalock, flags); |
| 6590 | list_for_each_entry(vport, &phba->port_list, listentry) { | 6611 | list_for_each_entry(vport, &phba->port_list, listentry) { |
| @@ -6641,8 +6662,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 6641 | vport = phba->pport; | 6662 | vport = phba->pport; |
| 6642 | else | 6663 | else |
| 6643 | vport = lpfc_find_vport_by_vpid(phba, | 6664 | vport = lpfc_find_vport_by_vpid(phba, |
| 6644 | icmd->unsli3.rcvsli3.vpi - phba->vpi_base); | 6665 | icmd->unsli3.rcvsli3.vpi); |
| 6645 | } | 6666 | } |
| 6667 | |||
| 6646 | /* If there are no BDEs associated | 6668 | /* If there are no BDEs associated |
| 6647 | * with this IOCB, there is nothing to do. | 6669 | * with this IOCB, there is nothing to do. |
| 6648 | */ | 6670 | */ |
| @@ -7222,7 +7244,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 7222 | elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; | 7244 | elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; |
| 7223 | elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; | 7245 | elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; |
| 7224 | /* Set the ulpContext to the vpi */ | 7246 | /* Set the ulpContext to the vpi */ |
| 7225 | elsiocb->iocb.ulpContext = vport->vpi + phba->vpi_base; | 7247 | elsiocb->iocb.ulpContext = phba->vpi_ids[vport->vpi]; |
| 7226 | } else { | 7248 | } else { |
| 7227 | /* For FDISC, Let FDISC rsp set the NPortID for this VPI */ | 7249 | /* For FDISC, Let FDISC rsp set the NPortID for this VPI */ |
| 7228 | icmd->ulpCt_h = 1; | 7250 | icmd->ulpCt_h = 1; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7a35df5e2038..18d0dbfda2bc 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -881,7 +881,7 @@ lpfc_linkdown(struct lpfc_hba *phba) | |||
| 881 | /* Clean up any firmware default rpi's */ | 881 | /* Clean up any firmware default rpi's */ |
| 882 | mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 882 | mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 883 | if (mb) { | 883 | if (mb) { |
| 884 | lpfc_unreg_did(phba, 0xffff, 0xffffffff, mb); | 884 | lpfc_unreg_did(phba, 0xffff, LPFC_UNREG_ALL_DFLT_RPIS, mb); |
| 885 | mb->vport = vport; | 885 | mb->vport = vport; |
| 886 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 886 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 887 | if (lpfc_sli_issue_mbox(phba, mb, MBX_NOWAIT) | 887 | if (lpfc_sli_issue_mbox(phba, mb, MBX_NOWAIT) |
| @@ -2690,16 +2690,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 2690 | 2690 | ||
| 2691 | memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt, | 2691 | memcpy((uint8_t *) &vport->fc_sparam, (uint8_t *) mp->virt, |
| 2692 | sizeof (struct serv_parm)); | 2692 | sizeof (struct serv_parm)); |
| 2693 | if (phba->cfg_soft_wwnn) | 2693 | lpfc_update_vport_wwn(vport); |
| 2694 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
| 2695 | vport->fc_sparam.nodeName.u.wwn); | ||
| 2696 | if (phba->cfg_soft_wwpn) | ||
| 2697 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
| 2698 | vport->fc_sparam.portName.u.wwn); | ||
| 2699 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
| 2700 | sizeof(vport->fc_nodename)); | ||
| 2701 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
| 2702 | sizeof(vport->fc_portname)); | ||
| 2703 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | 2694 | if (vport->port_type == LPFC_PHYSICAL_PORT) { |
| 2704 | memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn)); | 2695 | memcpy(&phba->wwnn, &vport->fc_nodename, sizeof(phba->wwnn)); |
| 2705 | memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn)); | 2696 | memcpy(&phba->wwpn, &vport->fc_portname, sizeof(phba->wwnn)); |
| @@ -3430,7 +3421,8 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 3430 | return; | 3421 | return; |
| 3431 | } | 3422 | } |
| 3432 | 3423 | ||
| 3433 | ndlp->nlp_rpi = mb->un.varWords[0]; | 3424 | if (phba->sli_rev < LPFC_SLI_REV4) |
| 3425 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
| 3434 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 3426 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
| 3435 | ndlp->nlp_type |= NLP_FABRIC; | 3427 | ndlp->nlp_type |= NLP_FABRIC; |
| 3436 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3428 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
| @@ -3504,7 +3496,8 @@ out: | |||
| 3504 | return; | 3496 | return; |
| 3505 | } | 3497 | } |
| 3506 | 3498 | ||
| 3507 | ndlp->nlp_rpi = mb->un.varWords[0]; | 3499 | if (phba->sli_rev < LPFC_SLI_REV4) |
| 3500 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
| 3508 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 3501 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
| 3509 | ndlp->nlp_type |= NLP_FABRIC; | 3502 | ndlp->nlp_type |= NLP_FABRIC; |
| 3510 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3503 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
| @@ -3591,7 +3584,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 3591 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) | 3584 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) |
| 3592 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 3585 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
| 3593 | 3586 | ||
| 3594 | |||
| 3595 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) | 3587 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) |
| 3596 | fc_remote_port_rolechg(rport, rport_ids.roles); | 3588 | fc_remote_port_rolechg(rport, rport_ids.roles); |
| 3597 | 3589 | ||
| @@ -4106,11 +4098,16 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 4106 | struct lpfc_hba *phba = vport->phba; | 4098 | struct lpfc_hba *phba = vport->phba; |
| 4107 | LPFC_MBOXQ_t *mbox; | 4099 | LPFC_MBOXQ_t *mbox; |
| 4108 | int rc; | 4100 | int rc; |
| 4101 | uint16_t rpi; | ||
| 4109 | 4102 | ||
| 4110 | if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { | 4103 | if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { |
| 4111 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4104 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 4112 | if (mbox) { | 4105 | if (mbox) { |
| 4113 | lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); | 4106 | /* SLI4 ports require the physical rpi value. */ |
| 4107 | rpi = ndlp->nlp_rpi; | ||
| 4108 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 4109 | rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
| 4110 | lpfc_unreg_login(phba, vport->vpi, rpi, mbox); | ||
| 4114 | mbox->vport = vport; | 4111 | mbox->vport = vport; |
| 4115 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4112 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 4116 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 4113 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
| @@ -4179,7 +4176,8 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) | |||
| 4179 | 4176 | ||
| 4180 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4177 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 4181 | if (mbox) { | 4178 | if (mbox) { |
| 4182 | lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox); | 4179 | lpfc_unreg_login(phba, vport->vpi, LPFC_UNREG_ALL_RPIS_VPORT, |
| 4180 | mbox); | ||
| 4183 | mbox->vport = vport; | 4181 | mbox->vport = vport; |
| 4184 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4182 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 4185 | mbox->context1 = NULL; | 4183 | mbox->context1 = NULL; |
| @@ -4203,7 +4201,8 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) | |||
| 4203 | 4201 | ||
| 4204 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4202 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 4205 | if (mbox) { | 4203 | if (mbox) { |
| 4206 | lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox); | 4204 | lpfc_unreg_did(phba, vport->vpi, LPFC_UNREG_ALL_DFLT_RPIS, |
| 4205 | mbox); | ||
| 4207 | mbox->vport = vport; | 4206 | mbox->vport = vport; |
| 4208 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4207 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 4209 | mbox->context1 = NULL; | 4208 | mbox->context1 = NULL; |
| @@ -4653,10 +4652,7 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
| 4653 | if (num_sent) | 4652 | if (num_sent) |
| 4654 | return; | 4653 | return; |
| 4655 | 4654 | ||
| 4656 | /* | 4655 | /* Register the VPI for SLI3, NON-NPIV only. */ |
| 4657 | * For SLI3, cmpl_reg_vpi will set port_state to READY, and | ||
| 4658 | * continue discovery. | ||
| 4659 | */ | ||
| 4660 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 4656 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
| 4661 | !(vport->fc_flag & FC_PT2PT) && | 4657 | !(vport->fc_flag & FC_PT2PT) && |
| 4662 | !(vport->fc_flag & FC_RSCN_MODE) && | 4658 | !(vport->fc_flag & FC_RSCN_MODE) && |
| @@ -4943,7 +4939,7 @@ restart_disc: | |||
| 4943 | if (phba->sli_rev < LPFC_SLI_REV4) { | 4939 | if (phba->sli_rev < LPFC_SLI_REV4) { |
| 4944 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) | 4940 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) |
| 4945 | lpfc_issue_reg_vpi(phba, vport); | 4941 | lpfc_issue_reg_vpi(phba, vport); |
| 4946 | else { /* NPIV Not enabled */ | 4942 | else { |
| 4947 | lpfc_issue_clear_la(phba, vport); | 4943 | lpfc_issue_clear_la(phba, vport); |
| 4948 | vport->port_state = LPFC_VPORT_READY; | 4944 | vport->port_state = LPFC_VPORT_READY; |
| 4949 | } | 4945 | } |
| @@ -5069,7 +5065,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 5069 | pmb->context1 = NULL; | 5065 | pmb->context1 = NULL; |
| 5070 | pmb->context2 = NULL; | 5066 | pmb->context2 = NULL; |
| 5071 | 5067 | ||
| 5072 | ndlp->nlp_rpi = mb->un.varWords[0]; | 5068 | if (phba->sli_rev < LPFC_SLI_REV4) |
| 5069 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
| 5073 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 5070 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
| 5074 | ndlp->nlp_type |= NLP_FABRIC; | 5071 | ndlp->nlp_type |= NLP_FABRIC; |
| 5075 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 5072 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
| @@ -5354,6 +5351,17 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) | |||
| 5354 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 5351 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
| 5355 | shost = lpfc_shost_from_vport(vports[i]); | 5352 | shost = lpfc_shost_from_vport(vports[i]); |
| 5356 | spin_lock_irq(shost->host_lock); | 5353 | spin_lock_irq(shost->host_lock); |
| 5354 | /* | ||
| 5355 | * IF the CVL_RCVD bit is not set then we have sent the | ||
| 5356 | * flogi. | ||
| 5357 | * If dev_loss fires while we are waiting we do not want to | ||
| 5358 | * unreg the fcf. | ||
| 5359 | */ | ||
| 5360 | if (!(vports[i]->fc_flag & FC_VPORT_CVL_RCVD)) { | ||
| 5361 | spin_unlock_irq(shost->host_lock); | ||
| 5362 | ret = 1; | ||
| 5363 | goto out; | ||
| 5364 | } | ||
| 5357 | list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { | 5365 | list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { |
| 5358 | if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport && | 5366 | if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport && |
| 5359 | (ndlp->rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { | 5367 | (ndlp->rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 86b6f7e6686a..9059524cf225 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
| @@ -64,6 +64,8 @@ | |||
| 64 | #define SLI3_IOCB_CMD_SIZE 128 | 64 | #define SLI3_IOCB_CMD_SIZE 128 |
| 65 | #define SLI3_IOCB_RSP_SIZE 64 | 65 | #define SLI3_IOCB_RSP_SIZE 64 |
| 66 | 66 | ||
| 67 | #define LPFC_UNREG_ALL_RPIS_VPORT 0xffff | ||
| 68 | #define LPFC_UNREG_ALL_DFLT_RPIS 0xffffffff | ||
| 67 | 69 | ||
| 68 | /* vendor ID used in SCSI netlink calls */ | 70 | /* vendor ID used in SCSI netlink calls */ |
| 69 | #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX) | 71 | #define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX) |
| @@ -903,6 +905,8 @@ struct RRQ { /* Structure is in Big Endian format */ | |||
| 903 | #define rrq_rxid_WORD rrq_exchg | 905 | #define rrq_rxid_WORD rrq_exchg |
| 904 | }; | 906 | }; |
| 905 | 907 | ||
| 908 | #define LPFC_MAX_VFN_PER_PFN 255 /* Maximum VFs allowed per ARI */ | ||
| 909 | #define LPFC_DEF_VFN_PER_PFN 0 /* Default VFs due to platform limitation*/ | ||
| 906 | 910 | ||
| 907 | struct RTV_RSP { /* Structure is in Big Endian format */ | 911 | struct RTV_RSP { /* Structure is in Big Endian format */ |
| 908 | uint32_t ratov; | 912 | uint32_t ratov; |
| @@ -1199,7 +1203,9 @@ typedef struct { | |||
| 1199 | #define PCI_DEVICE_ID_BALIUS 0xe131 | 1203 | #define PCI_DEVICE_ID_BALIUS 0xe131 |
| 1200 | #define PCI_DEVICE_ID_PROTEUS_PF 0xe180 | 1204 | #define PCI_DEVICE_ID_PROTEUS_PF 0xe180 |
| 1201 | #define PCI_DEVICE_ID_LANCER_FC 0xe200 | 1205 | #define PCI_DEVICE_ID_LANCER_FC 0xe200 |
| 1206 | #define PCI_DEVICE_ID_LANCER_FC_VF 0xe208 | ||
| 1202 | #define PCI_DEVICE_ID_LANCER_FCOE 0xe260 | 1207 | #define PCI_DEVICE_ID_LANCER_FCOE 0xe260 |
| 1208 | #define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268 | ||
| 1203 | #define PCI_DEVICE_ID_SAT_SMB 0xf011 | 1209 | #define PCI_DEVICE_ID_SAT_SMB 0xf011 |
| 1204 | #define PCI_DEVICE_ID_SAT_MID 0xf015 | 1210 | #define PCI_DEVICE_ID_SAT_MID 0xf015 |
| 1205 | #define PCI_DEVICE_ID_RFLY 0xf095 | 1211 | #define PCI_DEVICE_ID_RFLY 0xf095 |
| @@ -3021,7 +3027,7 @@ typedef struct { | |||
| 3021 | #define MAILBOX_EXT_SIZE (MAILBOX_EXT_WSIZE * sizeof(uint32_t)) | 3027 | #define MAILBOX_EXT_SIZE (MAILBOX_EXT_WSIZE * sizeof(uint32_t)) |
| 3022 | #define MAILBOX_HBA_EXT_OFFSET 0x100 | 3028 | #define MAILBOX_HBA_EXT_OFFSET 0x100 |
| 3023 | /* max mbox xmit size is a page size for sysfs IO operations */ | 3029 | /* max mbox xmit size is a page size for sysfs IO operations */ |
| 3024 | #define MAILBOX_MAX_XMIT_SIZE PAGE_SIZE | 3030 | #define MAILBOX_SYSFS_MAX 4096 |
| 3025 | 3031 | ||
| 3026 | typedef union { | 3032 | typedef union { |
| 3027 | uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/ | 3033 | uint32_t varWords[MAILBOX_CMD_WSIZE - 1]; /* first word is type/ |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 4dff668ebdad..11e26a26b5d1 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
| @@ -170,6 +170,25 @@ struct lpfc_sli_intf { | |||
| 170 | #define LPFC_PCI_FUNC3 3 | 170 | #define LPFC_PCI_FUNC3 3 |
| 171 | #define LPFC_PCI_FUNC4 4 | 171 | #define LPFC_PCI_FUNC4 4 |
| 172 | 172 | ||
| 173 | /* SLI4 interface type-2 control register offsets */ | ||
| 174 | #define LPFC_CTL_PORT_SEM_OFFSET 0x400 | ||
| 175 | #define LPFC_CTL_PORT_STA_OFFSET 0x404 | ||
| 176 | #define LPFC_CTL_PORT_CTL_OFFSET 0x408 | ||
| 177 | #define LPFC_CTL_PORT_ER1_OFFSET 0x40C | ||
| 178 | #define LPFC_CTL_PORT_ER2_OFFSET 0x410 | ||
| 179 | #define LPFC_CTL_PDEV_CTL_OFFSET 0x414 | ||
| 180 | |||
| 181 | /* Some SLI4 interface type-2 PDEV_CTL register bits */ | ||
| 182 | #define LPFC_CTL_PDEV_CTL_DRST 0x00000001 | ||
| 183 | #define LPFC_CTL_PDEV_CTL_FRST 0x00000002 | ||
| 184 | #define LPFC_CTL_PDEV_CTL_DD 0x00000004 | ||
| 185 | #define LPFC_CTL_PDEV_CTL_LC 0x00000008 | ||
| 186 | #define LPFC_CTL_PDEV_CTL_FRL_ALL 0x00 | ||
| 187 | #define LPFC_CTL_PDEV_CTL_FRL_FC_FCOE 0x10 | ||
| 188 | #define LPFC_CTL_PDEV_CTL_FRL_NIC 0x20 | ||
| 189 | |||
| 190 | #define LPFC_FW_DUMP_REQUEST (LPFC_CTL_PDEV_CTL_DD | LPFC_CTL_PDEV_CTL_FRST) | ||
| 191 | |||
| 173 | /* Active interrupt test count */ | 192 | /* Active interrupt test count */ |
| 174 | #define LPFC_ACT_INTR_CNT 4 | 193 | #define LPFC_ACT_INTR_CNT 4 |
| 175 | 194 | ||
| @@ -210,9 +229,26 @@ struct ulp_bde64 { | |||
| 210 | 229 | ||
| 211 | struct lpfc_sli4_flags { | 230 | struct lpfc_sli4_flags { |
| 212 | uint32_t word0; | 231 | uint32_t word0; |
| 213 | #define lpfc_fip_flag_SHIFT 0 | 232 | #define lpfc_idx_rsrc_rdy_SHIFT 0 |
| 214 | #define lpfc_fip_flag_MASK 0x00000001 | 233 | #define lpfc_idx_rsrc_rdy_MASK 0x00000001 |
| 215 | #define lpfc_fip_flag_WORD word0 | 234 | #define lpfc_idx_rsrc_rdy_WORD word0 |
| 235 | #define LPFC_IDX_RSRC_RDY 1 | ||
| 236 | #define lpfc_xri_rsrc_rdy_SHIFT 1 | ||
| 237 | #define lpfc_xri_rsrc_rdy_MASK 0x00000001 | ||
| 238 | #define lpfc_xri_rsrc_rdy_WORD word0 | ||
| 239 | #define LPFC_XRI_RSRC_RDY 1 | ||
| 240 | #define lpfc_rpi_rsrc_rdy_SHIFT 2 | ||
| 241 | #define lpfc_rpi_rsrc_rdy_MASK 0x00000001 | ||
| 242 | #define lpfc_rpi_rsrc_rdy_WORD word0 | ||
| 243 | #define LPFC_RPI_RSRC_RDY 1 | ||
| 244 | #define lpfc_vpi_rsrc_rdy_SHIFT 3 | ||
| 245 | #define lpfc_vpi_rsrc_rdy_MASK 0x00000001 | ||
| 246 | #define lpfc_vpi_rsrc_rdy_WORD word0 | ||
| 247 | #define LPFC_VPI_RSRC_RDY 1 | ||
| 248 | #define lpfc_vfi_rsrc_rdy_SHIFT 4 | ||
| 249 | #define lpfc_vfi_rsrc_rdy_MASK 0x00000001 | ||
| 250 | #define lpfc_vfi_rsrc_rdy_WORD word0 | ||
| 251 | #define LPFC_VFI_RSRC_RDY 1 | ||
| 216 | }; | 252 | }; |
| 217 | 253 | ||
| 218 | struct sli4_bls_rsp { | 254 | struct sli4_bls_rsp { |
| @@ -739,6 +775,12 @@ union lpfc_sli4_cfg_shdr { | |||
| 739 | #define lpfc_mbox_hdr_version_SHIFT 0 | 775 | #define lpfc_mbox_hdr_version_SHIFT 0 |
| 740 | #define lpfc_mbox_hdr_version_MASK 0x000000FF | 776 | #define lpfc_mbox_hdr_version_MASK 0x000000FF |
| 741 | #define lpfc_mbox_hdr_version_WORD word9 | 777 | #define lpfc_mbox_hdr_version_WORD word9 |
| 778 | #define lpfc_mbox_hdr_pf_num_SHIFT 16 | ||
| 779 | #define lpfc_mbox_hdr_pf_num_MASK 0x000000FF | ||
| 780 | #define lpfc_mbox_hdr_pf_num_WORD word9 | ||
| 781 | #define lpfc_mbox_hdr_vh_num_SHIFT 24 | ||
| 782 | #define lpfc_mbox_hdr_vh_num_MASK 0x000000FF | ||
| 783 | #define lpfc_mbox_hdr_vh_num_WORD word9 | ||
| 742 | #define LPFC_Q_CREATE_VERSION_2 2 | 784 | #define LPFC_Q_CREATE_VERSION_2 2 |
| 743 | #define LPFC_Q_CREATE_VERSION_1 1 | 785 | #define LPFC_Q_CREATE_VERSION_1 1 |
| 744 | #define LPFC_Q_CREATE_VERSION_0 0 | 786 | #define LPFC_Q_CREATE_VERSION_0 0 |
| @@ -766,12 +808,22 @@ union lpfc_sli4_cfg_shdr { | |||
| 766 | } response; | 808 | } response; |
| 767 | }; | 809 | }; |
| 768 | 810 | ||
| 769 | /* Mailbox structures */ | 811 | /* Mailbox Header structures. |
| 812 | * struct mbox_header is defined for first generation SLI4_CFG mailbox | ||
| 813 | * calls deployed for BE-based ports. | ||
| 814 | * | ||
| 815 | * struct sli4_mbox_header is defined for second generation SLI4 | ||
| 816 | * ports that don't deploy the SLI4_CFG mechanism. | ||
| 817 | */ | ||
| 770 | struct mbox_header { | 818 | struct mbox_header { |
| 771 | struct lpfc_sli4_cfg_mhdr cfg_mhdr; | 819 | struct lpfc_sli4_cfg_mhdr cfg_mhdr; |
| 772 | union lpfc_sli4_cfg_shdr cfg_shdr; | 820 | union lpfc_sli4_cfg_shdr cfg_shdr; |
| 773 | }; | 821 | }; |
| 774 | 822 | ||
| 823 | #define LPFC_EXTENT_LOCAL 0 | ||
| 824 | #define LPFC_TIMEOUT_DEFAULT 0 | ||
| 825 | #define LPFC_EXTENT_VERSION_DEFAULT 0 | ||
| 826 | |||
| 775 | /* Subsystem Definitions */ | 827 | /* Subsystem Definitions */ |
| 776 | #define LPFC_MBOX_SUBSYSTEM_COMMON 0x1 | 828 | #define LPFC_MBOX_SUBSYSTEM_COMMON 0x1 |
| 777 | #define LPFC_MBOX_SUBSYSTEM_FCOE 0xC | 829 | #define LPFC_MBOX_SUBSYSTEM_FCOE 0xC |
| @@ -794,6 +846,13 @@ struct mbox_header { | |||
| 794 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A | 846 | #define LPFC_MBOX_OPCODE_QUERY_FW_CFG 0x3A |
| 795 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D | 847 | #define LPFC_MBOX_OPCODE_FUNCTION_RESET 0x3D |
| 796 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A | 848 | #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A |
| 849 | #define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO 0x9A | ||
| 850 | #define LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT 0x9B | ||
| 851 | #define LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT 0x9C | ||
| 852 | #define LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT 0x9D | ||
| 853 | #define LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG 0xA0 | ||
| 854 | #define LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG 0xA4 | ||
| 855 | #define LPFC_MBOX_OPCODE_WRITE_OBJECT 0xAC | ||
| 797 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 | 856 | #define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5 |
| 798 | 857 | ||
| 799 | /* FCoE Opcodes */ | 858 | /* FCoE Opcodes */ |
| @@ -808,6 +867,8 @@ struct mbox_header { | |||
| 808 | #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A | 867 | #define LPFC_MBOX_OPCODE_FCOE_DELETE_FCF 0x0A |
| 809 | #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B | 868 | #define LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE 0x0B |
| 810 | #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 | 869 | #define LPFC_MBOX_OPCODE_FCOE_REDISCOVER_FCF 0x10 |
| 870 | #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE 0x22 | ||
| 871 | #define LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK 0x23 | ||
| 811 | 872 | ||
| 812 | /* Mailbox command structures */ | 873 | /* Mailbox command structures */ |
| 813 | struct eq_context { | 874 | struct eq_context { |
| @@ -1210,6 +1271,187 @@ struct lpfc_mbx_mq_destroy { | |||
| 1210 | } u; | 1271 | } u; |
| 1211 | }; | 1272 | }; |
| 1212 | 1273 | ||
| 1274 | /* Start Gen 2 SLI4 Mailbox definitions: */ | ||
| 1275 | |||
| 1276 | /* Define allocate-ready Gen 2 SLI4 FCoE Resource Extent Types. */ | ||
| 1277 | #define LPFC_RSC_TYPE_FCOE_VFI 0x20 | ||
| 1278 | #define LPFC_RSC_TYPE_FCOE_VPI 0x21 | ||
| 1279 | #define LPFC_RSC_TYPE_FCOE_RPI 0x22 | ||
| 1280 | #define LPFC_RSC_TYPE_FCOE_XRI 0x23 | ||
| 1281 | |||
| 1282 | struct lpfc_mbx_get_rsrc_extent_info { | ||
| 1283 | struct mbox_header header; | ||
| 1284 | union { | ||
| 1285 | struct { | ||
| 1286 | uint32_t word4; | ||
| 1287 | #define lpfc_mbx_get_rsrc_extent_info_type_SHIFT 0 | ||
| 1288 | #define lpfc_mbx_get_rsrc_extent_info_type_MASK 0x0000FFFF | ||
| 1289 | #define lpfc_mbx_get_rsrc_extent_info_type_WORD word4 | ||
| 1290 | } req; | ||
| 1291 | struct { | ||
| 1292 | uint32_t word4; | ||
| 1293 | #define lpfc_mbx_get_rsrc_extent_info_cnt_SHIFT 0 | ||
| 1294 | #define lpfc_mbx_get_rsrc_extent_info_cnt_MASK 0x0000FFFF | ||
| 1295 | #define lpfc_mbx_get_rsrc_extent_info_cnt_WORD word4 | ||
| 1296 | #define lpfc_mbx_get_rsrc_extent_info_size_SHIFT 16 | ||
| 1297 | #define lpfc_mbx_get_rsrc_extent_info_size_MASK 0x0000FFFF | ||
| 1298 | #define lpfc_mbx_get_rsrc_extent_info_size_WORD word4 | ||
| 1299 | } rsp; | ||
| 1300 | } u; | ||
| 1301 | }; | ||
| 1302 | |||
| 1303 | struct lpfc_id_range { | ||
| 1304 | uint32_t word5; | ||
| 1305 | #define lpfc_mbx_rsrc_id_word4_0_SHIFT 0 | ||
| 1306 | #define lpfc_mbx_rsrc_id_word4_0_MASK 0x0000FFFF | ||
| 1307 | #define lpfc_mbx_rsrc_id_word4_0_WORD word5 | ||
| 1308 | #define lpfc_mbx_rsrc_id_word4_1_SHIFT 16 | ||
| 1309 | #define lpfc_mbx_rsrc_id_word4_1_MASK 0x0000FFFF | ||
| 1310 | #define lpfc_mbx_rsrc_id_word4_1_WORD word5 | ||
| 1311 | }; | ||
| 1312 | |||
| 1313 | struct lpfc_mbx_set_link_diag_state { | ||
| 1314 | struct mbox_header header; | ||
| 1315 | union { | ||
| 1316 | struct { | ||
| 1317 | uint32_t word0; | ||
| 1318 | #define lpfc_mbx_set_diag_state_diag_SHIFT 0 | ||
| 1319 | #define lpfc_mbx_set_diag_state_diag_MASK 0x00000001 | ||
| 1320 | #define lpfc_mbx_set_diag_state_diag_WORD word0 | ||
| 1321 | #define lpfc_mbx_set_diag_state_link_num_SHIFT 16 | ||
| 1322 | #define lpfc_mbx_set_diag_state_link_num_MASK 0x0000003F | ||
| 1323 | #define lpfc_mbx_set_diag_state_link_num_WORD word0 | ||
| 1324 | #define lpfc_mbx_set_diag_state_link_type_SHIFT 22 | ||
| 1325 | #define lpfc_mbx_set_diag_state_link_type_MASK 0x00000003 | ||
| 1326 | #define lpfc_mbx_set_diag_state_link_type_WORD word0 | ||
| 1327 | } req; | ||
| 1328 | struct { | ||
| 1329 | uint32_t word0; | ||
| 1330 | } rsp; | ||
| 1331 | } u; | ||
| 1332 | }; | ||
| 1333 | |||
| 1334 | struct lpfc_mbx_set_link_diag_loopback { | ||
| 1335 | struct mbox_header header; | ||
| 1336 | union { | ||
| 1337 | struct { | ||
| 1338 | uint32_t word0; | ||
| 1339 | #define lpfc_mbx_set_diag_lpbk_type_SHIFT 0 | ||
| 1340 | #define lpfc_mbx_set_diag_lpbk_type_MASK 0x00000001 | ||
| 1341 | #define lpfc_mbx_set_diag_lpbk_type_WORD word0 | ||
| 1342 | #define LPFC_DIAG_LOOPBACK_TYPE_DISABLE 0x0 | ||
| 1343 | #define LPFC_DIAG_LOOPBACK_TYPE_INTERNAL 0x1 | ||
| 1344 | #define LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL 0x2 | ||
| 1345 | #define lpfc_mbx_set_diag_lpbk_link_num_SHIFT 16 | ||
| 1346 | #define lpfc_mbx_set_diag_lpbk_link_num_MASK 0x0000003F | ||
| 1347 | #define lpfc_mbx_set_diag_lpbk_link_num_WORD word0 | ||
| 1348 | #define lpfc_mbx_set_diag_lpbk_link_type_SHIFT 22 | ||
| 1349 | #define lpfc_mbx_set_diag_lpbk_link_type_MASK 0x00000003 | ||
| 1350 | #define lpfc_mbx_set_diag_lpbk_link_type_WORD word0 | ||
| 1351 | } req; | ||
| 1352 | struct { | ||
| 1353 | uint32_t word0; | ||
| 1354 | } rsp; | ||
| 1355 | } u; | ||
| 1356 | }; | ||
| 1357 | |||
| 1358 | struct lpfc_mbx_run_link_diag_test { | ||
| 1359 | struct mbox_header header; | ||
| 1360 | union { | ||
| 1361 | struct { | ||
| 1362 | uint32_t word0; | ||
| 1363 | #define lpfc_mbx_run_diag_test_link_num_SHIFT 16 | ||
| 1364 | #define lpfc_mbx_run_diag_test_link_num_MASK 0x0000003F | ||
| 1365 | #define lpfc_mbx_run_diag_test_link_num_WORD word0 | ||
| 1366 | #define lpfc_mbx_run_diag_test_link_type_SHIFT 22 | ||
| 1367 | #define lpfc_mbx_run_diag_test_link_type_MASK 0x00000003 | ||
| 1368 | #define lpfc_mbx_run_diag_test_link_type_WORD word0 | ||
| 1369 | uint32_t word1; | ||
| 1370 | #define lpfc_mbx_run_diag_test_test_id_SHIFT 0 | ||
| 1371 | #define lpfc_mbx_run_diag_test_test_id_MASK 0x0000FFFF | ||
| 1372 | #define lpfc_mbx_run_diag_test_test_id_WORD word1 | ||
| 1373 | #define lpfc_mbx_run_diag_test_loops_SHIFT 16 | ||
| 1374 | #define lpfc_mbx_run_diag_test_loops_MASK 0x0000FFFF | ||
| 1375 | #define lpfc_mbx_run_diag_test_loops_WORD word1 | ||
| 1376 | uint32_t word2; | ||
| 1377 | #define lpfc_mbx_run_diag_test_test_ver_SHIFT 0 | ||
| 1378 | #define lpfc_mbx_run_diag_test_test_ver_MASK 0x0000FFFF | ||
| 1379 | #define lpfc_mbx_run_diag_test_test_ver_WORD word2 | ||
| 1380 | #define lpfc_mbx_run_diag_test_err_act_SHIFT 16 | ||
| 1381 | #define lpfc_mbx_run_diag_test_err_act_MASK 0x000000FF | ||
| 1382 | #define lpfc_mbx_run_diag_test_err_act_WORD word2 | ||
| 1383 | } req; | ||
| 1384 | struct { | ||
| 1385 | uint32_t word0; | ||
| 1386 | } rsp; | ||
| 1387 | } u; | ||
| 1388 | }; | ||
| 1389 | |||
| 1390 | /* | ||
| 1391 | * struct lpfc_mbx_alloc_rsrc_extents: | ||
| 1392 | * A mbox is generically 256 bytes long. An SLI4_CONFIG mailbox requires | ||
| 1393 | * 6 words of header + 4 words of shared subcommand header + | ||
| 1394 | * 1 words of Extent-Opcode-specific header = 11 words or 44 bytes total. | ||
| 1395 | * | ||
| 1396 | * An embedded version of SLI4_CONFIG therefore has 256 - 44 = 212 bytes | ||
| 1397 | * for extents payload. | ||
| 1398 | * | ||
| 1399 | * 212/2 (bytes per extent) = 106 extents. | ||
| 1400 | * 106/2 (extents per word) = 53 words. | ||
| 1401 | * lpfc_id_range id is statically size to 53. | ||
| 1402 | * | ||
| 1403 | * This mailbox definition is used for ALLOC or GET_ALLOCATED | ||
| 1404 | * extent ranges. For ALLOC, the type and cnt are required. | ||
| 1405 | * For GET_ALLOCATED, only the type is required. | ||
| 1406 | */ | ||
| 1407 | struct lpfc_mbx_alloc_rsrc_extents { | ||
| 1408 | struct mbox_header header; | ||
| 1409 | union { | ||
| 1410 | struct { | ||
| 1411 | uint32_t word4; | ||
| 1412 | #define lpfc_mbx_alloc_rsrc_extents_type_SHIFT 0 | ||
| 1413 | #define lpfc_mbx_alloc_rsrc_extents_type_MASK 0x0000FFFF | ||
| 1414 | #define lpfc_mbx_alloc_rsrc_extents_type_WORD word4 | ||
| 1415 | #define lpfc_mbx_alloc_rsrc_extents_cnt_SHIFT 16 | ||
| 1416 | #define lpfc_mbx_alloc_rsrc_extents_cnt_MASK 0x0000FFFF | ||
| 1417 | #define lpfc_mbx_alloc_rsrc_extents_cnt_WORD word4 | ||
| 1418 | } req; | ||
| 1419 | struct { | ||
| 1420 | uint32_t word4; | ||
| 1421 | #define lpfc_mbx_rsrc_cnt_SHIFT 0 | ||
| 1422 | #define lpfc_mbx_rsrc_cnt_MASK 0x0000FFFF | ||
| 1423 | #define lpfc_mbx_rsrc_cnt_WORD word4 | ||
| 1424 | struct lpfc_id_range id[53]; | ||
| 1425 | } rsp; | ||
| 1426 | } u; | ||
| 1427 | }; | ||
| 1428 | |||
| 1429 | /* | ||
| 1430 | * This is the non-embedded version of ALLOC or GET RSRC_EXTENTS. Word4 in this | ||
| 1431 | * structure shares the same SHIFT/MASK/WORD defines provided in the | ||
| 1432 | * mbx_alloc_rsrc_extents and mbx_get_alloc_rsrc_extents, word4, provided in | ||
| 1433 | * the structures defined above. This non-embedded structure provides for the | ||
| 1434 | * maximum number of extents supported by the port. | ||
| 1435 | */ | ||
| 1436 | struct lpfc_mbx_nembed_rsrc_extent { | ||
| 1437 | union lpfc_sli4_cfg_shdr cfg_shdr; | ||
| 1438 | uint32_t word4; | ||
| 1439 | struct lpfc_id_range id; | ||
| 1440 | }; | ||
| 1441 | |||
| 1442 | struct lpfc_mbx_dealloc_rsrc_extents { | ||
| 1443 | struct mbox_header header; | ||
| 1444 | struct { | ||
| 1445 | uint32_t word4; | ||
| 1446 | #define lpfc_mbx_dealloc_rsrc_extents_type_SHIFT 0 | ||
| 1447 | #define lpfc_mbx_dealloc_rsrc_extents_type_MASK 0x0000FFFF | ||
| 1448 | #define lpfc_mbx_dealloc_rsrc_extents_type_WORD word4 | ||
| 1449 | } req; | ||
| 1450 | |||
| 1451 | }; | ||
| 1452 | |||
| 1453 | /* Start SLI4 FCoE specific mbox structures. */ | ||
| 1454 | |||
| 1213 | struct lpfc_mbx_post_hdr_tmpl { | 1455 | struct lpfc_mbx_post_hdr_tmpl { |
| 1214 | struct mbox_header header; | 1456 | struct mbox_header header; |
| 1215 | uint32_t word10; | 1457 | uint32_t word10; |
| @@ -1229,7 +1471,7 @@ struct sli4_sge { /* SLI-4 */ | |||
| 1229 | 1471 | ||
| 1230 | uint32_t word2; | 1472 | uint32_t word2; |
| 1231 | #define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/ | 1473 | #define lpfc_sli4_sge_offset_SHIFT 0 /* Offset of buffer - Not used*/ |
| 1232 | #define lpfc_sli4_sge_offset_MASK 0x00FFFFFF | 1474 | #define lpfc_sli4_sge_offset_MASK 0x1FFFFFFF |
| 1233 | #define lpfc_sli4_sge_offset_WORD word2 | 1475 | #define lpfc_sli4_sge_offset_WORD word2 |
| 1234 | #define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets | 1476 | #define lpfc_sli4_sge_last_SHIFT 31 /* Last SEG in the SGL sets |
| 1235 | this flag !! */ | 1477 | this flag !! */ |
| @@ -1773,61 +2015,31 @@ struct lpfc_mbx_read_rev { | |||
| 1773 | 2015 | ||
| 1774 | struct lpfc_mbx_read_config { | 2016 | struct lpfc_mbx_read_config { |
| 1775 | uint32_t word1; | 2017 | uint32_t word1; |
| 1776 | #define lpfc_mbx_rd_conf_max_bbc_SHIFT 0 | 2018 | #define lpfc_mbx_rd_conf_extnts_inuse_SHIFT 31 |
| 1777 | #define lpfc_mbx_rd_conf_max_bbc_MASK 0x000000FF | 2019 | #define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001 |
| 1778 | #define lpfc_mbx_rd_conf_max_bbc_WORD word1 | 2020 | #define lpfc_mbx_rd_conf_extnts_inuse_WORD word1 |
| 1779 | #define lpfc_mbx_rd_conf_init_bbc_SHIFT 8 | ||
| 1780 | #define lpfc_mbx_rd_conf_init_bbc_MASK 0x000000FF | ||
| 1781 | #define lpfc_mbx_rd_conf_init_bbc_WORD word1 | ||
| 1782 | uint32_t word2; | 2021 | uint32_t word2; |
| 1783 | #define lpfc_mbx_rd_conf_nport_did_SHIFT 0 | ||
| 1784 | #define lpfc_mbx_rd_conf_nport_did_MASK 0x00FFFFFF | ||
| 1785 | #define lpfc_mbx_rd_conf_nport_did_WORD word2 | ||
| 1786 | #define lpfc_mbx_rd_conf_topology_SHIFT 24 | 2022 | #define lpfc_mbx_rd_conf_topology_SHIFT 24 |
| 1787 | #define lpfc_mbx_rd_conf_topology_MASK 0x000000FF | 2023 | #define lpfc_mbx_rd_conf_topology_MASK 0x000000FF |
| 1788 | #define lpfc_mbx_rd_conf_topology_WORD word2 | 2024 | #define lpfc_mbx_rd_conf_topology_WORD word2 |
| 1789 | uint32_t word3; | 2025 | uint32_t rsvd_3; |
| 1790 | #define lpfc_mbx_rd_conf_ao_SHIFT 0 | ||
| 1791 | #define lpfc_mbx_rd_conf_ao_MASK 0x00000001 | ||
| 1792 | #define lpfc_mbx_rd_conf_ao_WORD word3 | ||
| 1793 | #define lpfc_mbx_rd_conf_bb_scn_SHIFT 8 | ||
| 1794 | #define lpfc_mbx_rd_conf_bb_scn_MASK 0x0000000F | ||
| 1795 | #define lpfc_mbx_rd_conf_bb_scn_WORD word3 | ||
| 1796 | #define lpfc_mbx_rd_conf_cbb_scn_SHIFT 12 | ||
| 1797 | #define lpfc_mbx_rd_conf_cbb_scn_MASK 0x0000000F | ||
| 1798 | #define lpfc_mbx_rd_conf_cbb_scn_WORD word3 | ||
| 1799 | #define lpfc_mbx_rd_conf_mc_SHIFT 29 | ||
| 1800 | #define lpfc_mbx_rd_conf_mc_MASK 0x00000001 | ||
| 1801 | #define lpfc_mbx_rd_conf_mc_WORD word3 | ||
| 1802 | uint32_t word4; | 2026 | uint32_t word4; |
| 1803 | #define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0 | 2027 | #define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0 |
| 1804 | #define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF | 2028 | #define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF |
| 1805 | #define lpfc_mbx_rd_conf_e_d_tov_WORD word4 | 2029 | #define lpfc_mbx_rd_conf_e_d_tov_WORD word4 |
| 1806 | uint32_t word5; | 2030 | uint32_t rsvd_5; |
| 1807 | #define lpfc_mbx_rd_conf_lp_tov_SHIFT 0 | ||
| 1808 | #define lpfc_mbx_rd_conf_lp_tov_MASK 0x0000FFFF | ||
| 1809 | #define lpfc_mbx_rd_conf_lp_tov_WORD word5 | ||
| 1810 | uint32_t word6; | 2031 | uint32_t word6; |
| 1811 | #define lpfc_mbx_rd_conf_r_a_tov_SHIFT 0 | 2032 | #define lpfc_mbx_rd_conf_r_a_tov_SHIFT 0 |
| 1812 | #define lpfc_mbx_rd_conf_r_a_tov_MASK 0x0000FFFF | 2033 | #define lpfc_mbx_rd_conf_r_a_tov_MASK 0x0000FFFF |
| 1813 | #define lpfc_mbx_rd_conf_r_a_tov_WORD word6 | 2034 | #define lpfc_mbx_rd_conf_r_a_tov_WORD word6 |
| 1814 | uint32_t word7; | 2035 | uint32_t rsvd_7; |
| 1815 | #define lpfc_mbx_rd_conf_r_t_tov_SHIFT 0 | 2036 | uint32_t rsvd_8; |
| 1816 | #define lpfc_mbx_rd_conf_r_t_tov_MASK 0x000000FF | ||
| 1817 | #define lpfc_mbx_rd_conf_r_t_tov_WORD word7 | ||
| 1818 | uint32_t word8; | ||
| 1819 | #define lpfc_mbx_rd_conf_al_tov_SHIFT 0 | ||
| 1820 | #define lpfc_mbx_rd_conf_al_tov_MASK 0x0000000F | ||
| 1821 | #define lpfc_mbx_rd_conf_al_tov_WORD word8 | ||
| 1822 | uint32_t word9; | 2037 | uint32_t word9; |
| 1823 | #define lpfc_mbx_rd_conf_lmt_SHIFT 0 | 2038 | #define lpfc_mbx_rd_conf_lmt_SHIFT 0 |
| 1824 | #define lpfc_mbx_rd_conf_lmt_MASK 0x0000FFFF | 2039 | #define lpfc_mbx_rd_conf_lmt_MASK 0x0000FFFF |
| 1825 | #define lpfc_mbx_rd_conf_lmt_WORD word9 | 2040 | #define lpfc_mbx_rd_conf_lmt_WORD word9 |
| 1826 | uint32_t word10; | 2041 | uint32_t rsvd_10; |
| 1827 | #define lpfc_mbx_rd_conf_max_alpa_SHIFT 0 | 2042 | uint32_t rsvd_11; |
| 1828 | #define lpfc_mbx_rd_conf_max_alpa_MASK 0x000000FF | ||
| 1829 | #define lpfc_mbx_rd_conf_max_alpa_WORD word10 | ||
| 1830 | uint32_t word11_rsvd; | ||
| 1831 | uint32_t word12; | 2043 | uint32_t word12; |
| 1832 | #define lpfc_mbx_rd_conf_xri_base_SHIFT 0 | 2044 | #define lpfc_mbx_rd_conf_xri_base_SHIFT 0 |
| 1833 | #define lpfc_mbx_rd_conf_xri_base_MASK 0x0000FFFF | 2045 | #define lpfc_mbx_rd_conf_xri_base_MASK 0x0000FFFF |
| @@ -1857,9 +2069,6 @@ struct lpfc_mbx_read_config { | |||
| 1857 | #define lpfc_mbx_rd_conf_vfi_count_MASK 0x0000FFFF | 2069 | #define lpfc_mbx_rd_conf_vfi_count_MASK 0x0000FFFF |
| 1858 | #define lpfc_mbx_rd_conf_vfi_count_WORD word15 | 2070 | #define lpfc_mbx_rd_conf_vfi_count_WORD word15 |
| 1859 | uint32_t word16; | 2071 | uint32_t word16; |
| 1860 | #define lpfc_mbx_rd_conf_fcfi_base_SHIFT 0 | ||
| 1861 | #define lpfc_mbx_rd_conf_fcfi_base_MASK 0x0000FFFF | ||
| 1862 | #define lpfc_mbx_rd_conf_fcfi_base_WORD word16 | ||
| 1863 | #define lpfc_mbx_rd_conf_fcfi_count_SHIFT 16 | 2072 | #define lpfc_mbx_rd_conf_fcfi_count_SHIFT 16 |
| 1864 | #define lpfc_mbx_rd_conf_fcfi_count_MASK 0x0000FFFF | 2073 | #define lpfc_mbx_rd_conf_fcfi_count_MASK 0x0000FFFF |
| 1865 | #define lpfc_mbx_rd_conf_fcfi_count_WORD word16 | 2074 | #define lpfc_mbx_rd_conf_fcfi_count_WORD word16 |
| @@ -2169,6 +2378,12 @@ struct lpfc_sli4_parameters { | |||
| 2169 | #define cfg_fcoe_SHIFT 0 | 2378 | #define cfg_fcoe_SHIFT 0 |
| 2170 | #define cfg_fcoe_MASK 0x00000001 | 2379 | #define cfg_fcoe_MASK 0x00000001 |
| 2171 | #define cfg_fcoe_WORD word12 | 2380 | #define cfg_fcoe_WORD word12 |
| 2381 | #define cfg_ext_SHIFT 1 | ||
| 2382 | #define cfg_ext_MASK 0x00000001 | ||
| 2383 | #define cfg_ext_WORD word12 | ||
| 2384 | #define cfg_hdrr_SHIFT 2 | ||
| 2385 | #define cfg_hdrr_MASK 0x00000001 | ||
| 2386 | #define cfg_hdrr_WORD word12 | ||
| 2172 | #define cfg_phwq_SHIFT 15 | 2387 | #define cfg_phwq_SHIFT 15 |
| 2173 | #define cfg_phwq_MASK 0x00000001 | 2388 | #define cfg_phwq_MASK 0x00000001 |
| 2174 | #define cfg_phwq_WORD word12 | 2389 | #define cfg_phwq_WORD word12 |
| @@ -2198,6 +2413,145 @@ struct lpfc_mbx_get_sli4_parameters { | |||
| 2198 | struct lpfc_sli4_parameters sli4_parameters; | 2413 | struct lpfc_sli4_parameters sli4_parameters; |
| 2199 | }; | 2414 | }; |
| 2200 | 2415 | ||
| 2416 | struct lpfc_rscr_desc_generic { | ||
| 2417 | #define LPFC_RSRC_DESC_WSIZE 18 | ||
| 2418 | uint32_t desc[LPFC_RSRC_DESC_WSIZE]; | ||
| 2419 | }; | ||
| 2420 | |||
| 2421 | struct lpfc_rsrc_desc_pcie { | ||
| 2422 | uint32_t word0; | ||
| 2423 | #define lpfc_rsrc_desc_pcie_type_SHIFT 0 | ||
| 2424 | #define lpfc_rsrc_desc_pcie_type_MASK 0x000000ff | ||
| 2425 | #define lpfc_rsrc_desc_pcie_type_WORD word0 | ||
| 2426 | #define LPFC_RSRC_DESC_TYPE_PCIE 0x40 | ||
| 2427 | uint32_t word1; | ||
| 2428 | #define lpfc_rsrc_desc_pcie_pfnum_SHIFT 0 | ||
| 2429 | #define lpfc_rsrc_desc_pcie_pfnum_MASK 0x000000ff | ||
| 2430 | #define lpfc_rsrc_desc_pcie_pfnum_WORD word1 | ||
| 2431 | uint32_t reserved; | ||
| 2432 | uint32_t word3; | ||
| 2433 | #define lpfc_rsrc_desc_pcie_sriov_sta_SHIFT 0 | ||
| 2434 | #define lpfc_rsrc_desc_pcie_sriov_sta_MASK 0x000000ff | ||
| 2435 | #define lpfc_rsrc_desc_pcie_sriov_sta_WORD word3 | ||
| 2436 | #define lpfc_rsrc_desc_pcie_pf_sta_SHIFT 8 | ||
| 2437 | #define lpfc_rsrc_desc_pcie_pf_sta_MASK 0x000000ff | ||
| 2438 | #define lpfc_rsrc_desc_pcie_pf_sta_WORD word3 | ||
| 2439 | #define lpfc_rsrc_desc_pcie_pf_type_SHIFT 16 | ||
| 2440 | #define lpfc_rsrc_desc_pcie_pf_type_MASK 0x000000ff | ||
| 2441 | #define lpfc_rsrc_desc_pcie_pf_type_WORD word3 | ||
| 2442 | uint32_t word4; | ||
| 2443 | #define lpfc_rsrc_desc_pcie_nr_virtfn_SHIFT 0 | ||
| 2444 | #define lpfc_rsrc_desc_pcie_nr_virtfn_MASK 0x0000ffff | ||
| 2445 | #define lpfc_rsrc_desc_pcie_nr_virtfn_WORD word4 | ||
| 2446 | }; | ||
| 2447 | |||
| 2448 | struct lpfc_rsrc_desc_fcfcoe { | ||
| 2449 | uint32_t word0; | ||
| 2450 | #define lpfc_rsrc_desc_fcfcoe_type_SHIFT 0 | ||
| 2451 | #define lpfc_rsrc_desc_fcfcoe_type_MASK 0x000000ff | ||
| 2452 | #define lpfc_rsrc_desc_fcfcoe_type_WORD word0 | ||
| 2453 | #define LPFC_RSRC_DESC_TYPE_FCFCOE 0x43 | ||
| 2454 | uint32_t word1; | ||
| 2455 | #define lpfc_rsrc_desc_fcfcoe_vfnum_SHIFT 0 | ||
| 2456 | #define lpfc_rsrc_desc_fcfcoe_vfnum_MASK 0x000000ff | ||
| 2457 | #define lpfc_rsrc_desc_fcfcoe_vfnum_WORD word1 | ||
| 2458 | #define lpfc_rsrc_desc_fcfcoe_pfnum_SHIFT 16 | ||
| 2459 | #define lpfc_rsrc_desc_fcfcoe_pfnum_MASK 0x000007ff | ||
| 2460 | #define lpfc_rsrc_desc_fcfcoe_pfnum_WORD word1 | ||
| 2461 | uint32_t word2; | ||
| 2462 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_SHIFT 0 | ||
| 2463 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_MASK 0x0000ffff | ||
| 2464 | #define lpfc_rsrc_desc_fcfcoe_rpi_cnt_WORD word2 | ||
| 2465 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_SHIFT 16 | ||
| 2466 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_MASK 0x0000ffff | ||
| 2467 | #define lpfc_rsrc_desc_fcfcoe_xri_cnt_WORD word2 | ||
| 2468 | uint32_t word3; | ||
| 2469 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_SHIFT 0 | ||
| 2470 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_MASK 0x0000ffff | ||
| 2471 | #define lpfc_rsrc_desc_fcfcoe_wq_cnt_WORD word3 | ||
| 2472 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_SHIFT 16 | ||
| 2473 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_MASK 0x0000ffff | ||
| 2474 | #define lpfc_rsrc_desc_fcfcoe_rq_cnt_WORD word3 | ||
| 2475 | uint32_t word4; | ||
| 2476 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_SHIFT 0 | ||
| 2477 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_MASK 0x0000ffff | ||
| 2478 | #define lpfc_rsrc_desc_fcfcoe_cq_cnt_WORD word4 | ||
| 2479 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_SHIFT 16 | ||
| 2480 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_MASK 0x0000ffff | ||
| 2481 | #define lpfc_rsrc_desc_fcfcoe_vpi_cnt_WORD word4 | ||
| 2482 | uint32_t word5; | ||
| 2483 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_SHIFT 0 | ||
| 2484 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_MASK 0x0000ffff | ||
| 2485 | #define lpfc_rsrc_desc_fcfcoe_fcfi_cnt_WORD word5 | ||
| 2486 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_SHIFT 16 | ||
| 2487 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_MASK 0x0000ffff | ||
| 2488 | #define lpfc_rsrc_desc_fcfcoe_vfi_cnt_WORD word5 | ||
| 2489 | uint32_t word6; | ||
| 2490 | uint32_t word7; | ||
| 2491 | uint32_t word8; | ||
| 2492 | uint32_t word9; | ||
| 2493 | uint32_t word10; | ||
| 2494 | uint32_t word11; | ||
| 2495 | uint32_t word12; | ||
| 2496 | uint32_t word13; | ||
| 2497 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_SHIFT 0 | ||
| 2498 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_MASK 0x0000003f | ||
| 2499 | #define lpfc_rsrc_desc_fcfcoe_lnk_nr_WORD word13 | ||
| 2500 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_SHIFT 6 | ||
| 2501 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_MASK 0x00000003 | ||
| 2502 | #define lpfc_rsrc_desc_fcfcoe_lnk_tp_WORD word13 | ||
| 2503 | #define lpfc_rsrc_desc_fcfcoe_lmc_SHIFT 8 | ||
| 2504 | #define lpfc_rsrc_desc_fcfcoe_lmc_MASK 0x00000001 | ||
| 2505 | #define lpfc_rsrc_desc_fcfcoe_lmc_WORD word13 | ||
| 2506 | #define lpfc_rsrc_desc_fcfcoe_lld_SHIFT 9 | ||
| 2507 | #define lpfc_rsrc_desc_fcfcoe_lld_MASK 0x00000001 | ||
| 2508 | #define lpfc_rsrc_desc_fcfcoe_lld_WORD word13 | ||
| 2509 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_SHIFT 16 | ||
| 2510 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_MASK 0x0000ffff | ||
| 2511 | #define lpfc_rsrc_desc_fcfcoe_eq_cnt_WORD word13 | ||
| 2512 | }; | ||
| 2513 | |||
| 2514 | struct lpfc_func_cfg { | ||
| 2515 | #define LPFC_RSRC_DESC_MAX_NUM 2 | ||
| 2516 | uint32_t rsrc_desc_count; | ||
| 2517 | struct lpfc_rscr_desc_generic desc[LPFC_RSRC_DESC_MAX_NUM]; | ||
| 2518 | }; | ||
| 2519 | |||
| 2520 | struct lpfc_mbx_get_func_cfg { | ||
| 2521 | struct mbox_header header; | ||
| 2522 | #define LPFC_CFG_TYPE_PERSISTENT_OVERRIDE 0x0 | ||
| 2523 | #define LPFC_CFG_TYPE_FACTURY_DEFAULT 0x1 | ||
| 2524 | #define LPFC_CFG_TYPE_CURRENT_ACTIVE 0x2 | ||
| 2525 | struct lpfc_func_cfg func_cfg; | ||
| 2526 | }; | ||
| 2527 | |||
| 2528 | struct lpfc_prof_cfg { | ||
| 2529 | #define LPFC_RSRC_DESC_MAX_NUM 2 | ||
| 2530 | uint32_t rsrc_desc_count; | ||
| 2531 | struct lpfc_rscr_desc_generic desc[LPFC_RSRC_DESC_MAX_NUM]; | ||
| 2532 | }; | ||
| 2533 | |||
| 2534 | struct lpfc_mbx_get_prof_cfg { | ||
| 2535 | struct mbox_header header; | ||
| 2536 | #define LPFC_CFG_TYPE_PERSISTENT_OVERRIDE 0x0 | ||
| 2537 | #define LPFC_CFG_TYPE_FACTURY_DEFAULT 0x1 | ||
| 2538 | #define LPFC_CFG_TYPE_CURRENT_ACTIVE 0x2 | ||
| 2539 | union { | ||
| 2540 | struct { | ||
| 2541 | uint32_t word10; | ||
| 2542 | #define lpfc_mbx_get_prof_cfg_prof_id_SHIFT 0 | ||
| 2543 | #define lpfc_mbx_get_prof_cfg_prof_id_MASK 0x000000ff | ||
| 2544 | #define lpfc_mbx_get_prof_cfg_prof_id_WORD word10 | ||
| 2545 | #define lpfc_mbx_get_prof_cfg_prof_tp_SHIFT 8 | ||
| 2546 | #define lpfc_mbx_get_prof_cfg_prof_tp_MASK 0x00000003 | ||
| 2547 | #define lpfc_mbx_get_prof_cfg_prof_tp_WORD word10 | ||
| 2548 | } request; | ||
| 2549 | struct { | ||
| 2550 | struct lpfc_prof_cfg prof_cfg; | ||
| 2551 | } response; | ||
| 2552 | } u; | ||
| 2553 | }; | ||
| 2554 | |||
| 2201 | /* Mailbox Completion Queue Error Messages */ | 2555 | /* Mailbox Completion Queue Error Messages */ |
| 2202 | #define MB_CQE_STATUS_SUCCESS 0x0 | 2556 | #define MB_CQE_STATUS_SUCCESS 0x0 |
| 2203 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 | 2557 | #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES 0x1 |
| @@ -2206,6 +2560,29 @@ struct lpfc_mbx_get_sli4_parameters { | |||
| 2206 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 | 2560 | #define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4 |
| 2207 | #define MB_CQE_STATUS_DMA_FAILED 0x5 | 2561 | #define MB_CQE_STATUS_DMA_FAILED 0x5 |
| 2208 | 2562 | ||
| 2563 | #define LPFC_MBX_WR_CONFIG_MAX_BDE 8 | ||
| 2564 | struct lpfc_mbx_wr_object { | ||
| 2565 | struct mbox_header header; | ||
| 2566 | union { | ||
| 2567 | struct { | ||
| 2568 | uint32_t word4; | ||
| 2569 | #define lpfc_wr_object_eof_SHIFT 31 | ||
| 2570 | #define lpfc_wr_object_eof_MASK 0x00000001 | ||
| 2571 | #define lpfc_wr_object_eof_WORD word4 | ||
| 2572 | #define lpfc_wr_object_write_length_SHIFT 0 | ||
| 2573 | #define lpfc_wr_object_write_length_MASK 0x00FFFFFF | ||
| 2574 | #define lpfc_wr_object_write_length_WORD word4 | ||
| 2575 | uint32_t write_offset; | ||
| 2576 | uint32_t object_name[26]; | ||
| 2577 | uint32_t bde_count; | ||
| 2578 | struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE]; | ||
| 2579 | } request; | ||
| 2580 | struct { | ||
| 2581 | uint32_t actual_write_length; | ||
| 2582 | } response; | ||
| 2583 | } u; | ||
| 2584 | }; | ||
| 2585 | |||
| 2209 | /* mailbox queue entry structure */ | 2586 | /* mailbox queue entry structure */ |
| 2210 | struct lpfc_mqe { | 2587 | struct lpfc_mqe { |
| 2211 | uint32_t word0; | 2588 | uint32_t word0; |
| @@ -2241,6 +2618,9 @@ struct lpfc_mqe { | |||
| 2241 | struct lpfc_mbx_cq_destroy cq_destroy; | 2618 | struct lpfc_mbx_cq_destroy cq_destroy; |
| 2242 | struct lpfc_mbx_wq_destroy wq_destroy; | 2619 | struct lpfc_mbx_wq_destroy wq_destroy; |
| 2243 | struct lpfc_mbx_rq_destroy rq_destroy; | 2620 | struct lpfc_mbx_rq_destroy rq_destroy; |
| 2621 | struct lpfc_mbx_get_rsrc_extent_info rsrc_extent_info; | ||
| 2622 | struct lpfc_mbx_alloc_rsrc_extents alloc_rsrc_extents; | ||
| 2623 | struct lpfc_mbx_dealloc_rsrc_extents dealloc_rsrc_extents; | ||
| 2244 | struct lpfc_mbx_post_sgl_pages post_sgl_pages; | 2624 | struct lpfc_mbx_post_sgl_pages post_sgl_pages; |
| 2245 | struct lpfc_mbx_nembed_cmd nembed_cmd; | 2625 | struct lpfc_mbx_nembed_cmd nembed_cmd; |
| 2246 | struct lpfc_mbx_read_rev read_rev; | 2626 | struct lpfc_mbx_read_rev read_rev; |
| @@ -2252,7 +2632,13 @@ struct lpfc_mqe { | |||
| 2252 | struct lpfc_mbx_supp_pages supp_pages; | 2632 | struct lpfc_mbx_supp_pages supp_pages; |
| 2253 | struct lpfc_mbx_pc_sli4_params sli4_params; | 2633 | struct lpfc_mbx_pc_sli4_params sli4_params; |
| 2254 | struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; | 2634 | struct lpfc_mbx_get_sli4_parameters get_sli4_parameters; |
| 2635 | struct lpfc_mbx_set_link_diag_state link_diag_state; | ||
| 2636 | struct lpfc_mbx_set_link_diag_loopback link_diag_loopback; | ||
| 2637 | struct lpfc_mbx_run_link_diag_test link_diag_test; | ||
| 2638 | struct lpfc_mbx_get_func_cfg get_func_cfg; | ||
| 2639 | struct lpfc_mbx_get_prof_cfg get_prof_cfg; | ||
| 2255 | struct lpfc_mbx_nop nop; | 2640 | struct lpfc_mbx_nop nop; |
| 2641 | struct lpfc_mbx_wr_object wr_object; | ||
| 2256 | } un; | 2642 | } un; |
| 2257 | }; | 2643 | }; |
| 2258 | 2644 | ||
| @@ -2458,7 +2844,7 @@ struct lpfc_bmbx_create { | |||
| 2458 | #define SGL_ALIGN_SZ 64 | 2844 | #define SGL_ALIGN_SZ 64 |
| 2459 | #define SGL_PAGE_SIZE 4096 | 2845 | #define SGL_PAGE_SIZE 4096 |
| 2460 | /* align SGL addr on a size boundary - adjust address up */ | 2846 | /* align SGL addr on a size boundary - adjust address up */ |
| 2461 | #define NO_XRI ((uint16_t)-1) | 2847 | #define NO_XRI 0xffff |
| 2462 | 2848 | ||
| 2463 | struct wqe_common { | 2849 | struct wqe_common { |
| 2464 | uint32_t word6; | 2850 | uint32_t word6; |
| @@ -2798,9 +3184,28 @@ union lpfc_wqe { | |||
| 2798 | struct gen_req64_wqe gen_req; | 3184 | struct gen_req64_wqe gen_req; |
| 2799 | }; | 3185 | }; |
| 2800 | 3186 | ||
| 3187 | #define LPFC_GROUP_OJECT_MAGIC_NUM 0xfeaa0001 | ||
| 3188 | #define LPFC_FILE_TYPE_GROUP 0xf7 | ||
| 3189 | #define LPFC_FILE_ID_GROUP 0xa2 | ||
| 3190 | struct lpfc_grp_hdr { | ||
| 3191 | uint32_t size; | ||
| 3192 | uint32_t magic_number; | ||
| 3193 | uint32_t word2; | ||
| 3194 | #define lpfc_grp_hdr_file_type_SHIFT 24 | ||
| 3195 | #define lpfc_grp_hdr_file_type_MASK 0x000000FF | ||
| 3196 | #define lpfc_grp_hdr_file_type_WORD word2 | ||
| 3197 | #define lpfc_grp_hdr_id_SHIFT 16 | ||
| 3198 | #define lpfc_grp_hdr_id_MASK 0x000000FF | ||
| 3199 | #define lpfc_grp_hdr_id_WORD word2 | ||
| 3200 | uint8_t rev_name[128]; | ||
| 3201 | }; | ||
| 3202 | |||
| 2801 | #define FCP_COMMAND 0x0 | 3203 | #define FCP_COMMAND 0x0 |
| 2802 | #define FCP_COMMAND_DATA_OUT 0x1 | 3204 | #define FCP_COMMAND_DATA_OUT 0x1 |
| 2803 | #define ELS_COMMAND_NON_FIP 0xC | 3205 | #define ELS_COMMAND_NON_FIP 0xC |
| 2804 | #define ELS_COMMAND_FIP 0xD | 3206 | #define ELS_COMMAND_FIP 0xD |
| 2805 | #define OTHER_COMMAND 0x8 | 3207 | #define OTHER_COMMAND 0x8 |
| 2806 | 3208 | ||
| 3209 | #define LPFC_FW_DUMP 1 | ||
| 3210 | #define LPFC_FW_RESET 2 | ||
| 3211 | #define LPFC_DV_RESET 3 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7dda036a1af3..148b98ddbb1d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
| 31 | #include <linux/aer.h> | 31 | #include <linux/aer.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/firmware.h> | ||
| 33 | 34 | ||
| 34 | #include <scsi/scsi.h> | 35 | #include <scsi/scsi.h> |
| 35 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
| @@ -211,7 +212,6 @@ lpfc_config_port_prep(struct lpfc_hba *phba) | |||
| 211 | lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL); | 212 | lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL); |
| 212 | if (!lpfc_vpd_data) | 213 | if (!lpfc_vpd_data) |
| 213 | goto out_free_mbox; | 214 | goto out_free_mbox; |
| 214 | |||
| 215 | do { | 215 | do { |
| 216 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD); | 216 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD); |
| 217 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 217 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
| @@ -309,6 +309,45 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /** | 311 | /** |
| 312 | * lpfc_update_vport_wwn - Updates the fc_nodename, fc_portname, | ||
| 313 | * cfg_soft_wwnn, cfg_soft_wwpn | ||
| 314 | * @vport: pointer to lpfc vport data structure. | ||
| 315 | * | ||
| 316 | * | ||
| 317 | * Return codes | ||
| 318 | * None. | ||
| 319 | **/ | ||
| 320 | void | ||
| 321 | lpfc_update_vport_wwn(struct lpfc_vport *vport) | ||
| 322 | { | ||
| 323 | /* If the soft name exists then update it using the service params */ | ||
| 324 | if (vport->phba->cfg_soft_wwnn) | ||
| 325 | u64_to_wwn(vport->phba->cfg_soft_wwnn, | ||
| 326 | vport->fc_sparam.nodeName.u.wwn); | ||
| 327 | if (vport->phba->cfg_soft_wwpn) | ||
| 328 | u64_to_wwn(vport->phba->cfg_soft_wwpn, | ||
| 329 | vport->fc_sparam.portName.u.wwn); | ||
| 330 | |||
| 331 | /* | ||
| 332 | * If the name is empty or there exists a soft name | ||
| 333 | * then copy the service params name, otherwise use the fc name | ||
| 334 | */ | ||
| 335 | if (vport->fc_nodename.u.wwn[0] == 0 || vport->phba->cfg_soft_wwnn) | ||
| 336 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
| 337 | sizeof(struct lpfc_name)); | ||
| 338 | else | ||
| 339 | memcpy(&vport->fc_sparam.nodeName, &vport->fc_nodename, | ||
| 340 | sizeof(struct lpfc_name)); | ||
| 341 | |||
| 342 | if (vport->fc_portname.u.wwn[0] == 0 || vport->phba->cfg_soft_wwpn) | ||
| 343 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
| 344 | sizeof(struct lpfc_name)); | ||
| 345 | else | ||
| 346 | memcpy(&vport->fc_sparam.portName, &vport->fc_portname, | ||
| 347 | sizeof(struct lpfc_name)); | ||
| 348 | } | ||
| 349 | |||
| 350 | /** | ||
| 312 | * lpfc_config_port_post - Perform lpfc initialization after config port | 351 | * lpfc_config_port_post - Perform lpfc initialization after config port |
| 313 | * @phba: pointer to lpfc hba data structure. | 352 | * @phba: pointer to lpfc hba data structure. |
| 314 | * | 353 | * |
| @@ -377,17 +416,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
| 377 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 416 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
| 378 | kfree(mp); | 417 | kfree(mp); |
| 379 | pmb->context1 = NULL; | 418 | pmb->context1 = NULL; |
| 380 | 419 | lpfc_update_vport_wwn(vport); | |
| 381 | if (phba->cfg_soft_wwnn) | ||
| 382 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
| 383 | vport->fc_sparam.nodeName.u.wwn); | ||
| 384 | if (phba->cfg_soft_wwpn) | ||
| 385 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
| 386 | vport->fc_sparam.portName.u.wwn); | ||
| 387 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
| 388 | sizeof (struct lpfc_name)); | ||
| 389 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
| 390 | sizeof (struct lpfc_name)); | ||
| 391 | 420 | ||
| 392 | /* Update the fc_host data structures with new wwn. */ | 421 | /* Update the fc_host data structures with new wwn. */ |
| 393 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); | 422 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); |
| @@ -573,7 +602,6 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
| 573 | /* Clear all pending interrupts */ | 602 | /* Clear all pending interrupts */ |
| 574 | writel(0xffffffff, phba->HAregaddr); | 603 | writel(0xffffffff, phba->HAregaddr); |
| 575 | readl(phba->HAregaddr); /* flush */ | 604 | readl(phba->HAregaddr); /* flush */ |
| 576 | |||
| 577 | phba->link_state = LPFC_HBA_ERROR; | 605 | phba->link_state = LPFC_HBA_ERROR; |
| 578 | if (rc != MBX_BUSY) | 606 | if (rc != MBX_BUSY) |
| 579 | mempool_free(pmb, phba->mbox_mem_pool); | 607 | mempool_free(pmb, phba->mbox_mem_pool); |
| @@ -1755,7 +1783,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
| 1755 | && descp && descp[0] != '\0') | 1783 | && descp && descp[0] != '\0') |
| 1756 | return; | 1784 | return; |
| 1757 | 1785 | ||
| 1758 | if (phba->lmt & LMT_10Gb) | 1786 | if (phba->lmt & LMT_16Gb) |
| 1787 | max_speed = 16; | ||
| 1788 | else if (phba->lmt & LMT_10Gb) | ||
| 1759 | max_speed = 10; | 1789 | max_speed = 10; |
| 1760 | else if (phba->lmt & LMT_8Gb) | 1790 | else if (phba->lmt & LMT_8Gb) |
| 1761 | max_speed = 8; | 1791 | max_speed = 8; |
| @@ -1922,12 +1952,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
| 1922 | "Fibre Channel Adapter"}; | 1952 | "Fibre Channel Adapter"}; |
| 1923 | break; | 1953 | break; |
| 1924 | case PCI_DEVICE_ID_LANCER_FC: | 1954 | case PCI_DEVICE_ID_LANCER_FC: |
| 1925 | oneConnect = 1; | 1955 | case PCI_DEVICE_ID_LANCER_FC_VF: |
| 1926 | m = (typeof(m)){"Undefined", "PCIe", "Fibre Channel Adapter"}; | 1956 | m = (typeof(m)){"LPe16000", "PCIe", "Fibre Channel Adapter"}; |
| 1927 | break; | 1957 | break; |
| 1928 | case PCI_DEVICE_ID_LANCER_FCOE: | 1958 | case PCI_DEVICE_ID_LANCER_FCOE: |
| 1959 | case PCI_DEVICE_ID_LANCER_FCOE_VF: | ||
| 1929 | oneConnect = 1; | 1960 | oneConnect = 1; |
| 1930 | m = (typeof(m)){"Undefined", "PCIe", "FCoE"}; | 1961 | m = (typeof(m)){"OCe50100", "PCIe", "FCoE"}; |
| 1931 | break; | 1962 | break; |
| 1932 | default: | 1963 | default: |
| 1933 | m = (typeof(m)){"Unknown", "", ""}; | 1964 | m = (typeof(m)){"Unknown", "", ""}; |
| @@ -1936,7 +1967,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) | |||
| 1936 | 1967 | ||
| 1937 | if (mdp && mdp[0] == '\0') | 1968 | if (mdp && mdp[0] == '\0') |
| 1938 | snprintf(mdp, 79,"%s", m.name); | 1969 | snprintf(mdp, 79,"%s", m.name); |
| 1939 | /* oneConnect hba requires special processing, they are all initiators | 1970 | /* |
| 1971 | * oneConnect hba requires special processing, they are all initiators | ||
| 1940 | * and we put the port number on the end | 1972 | * and we put the port number on the end |
| 1941 | */ | 1973 | */ |
| 1942 | if (descp && descp[0] == '\0') { | 1974 | if (descp && descp[0] == '\0') { |
| @@ -2656,6 +2688,7 @@ lpfc_scsi_free(struct lpfc_hba *phba) | |||
| 2656 | kfree(io); | 2688 | kfree(io); |
| 2657 | phba->total_iocbq_bufs--; | 2689 | phba->total_iocbq_bufs--; |
| 2658 | } | 2690 | } |
| 2691 | |||
| 2659 | spin_unlock_irq(&phba->hbalock); | 2692 | spin_unlock_irq(&phba->hbalock); |
| 2660 | return 0; | 2693 | return 0; |
| 2661 | } | 2694 | } |
| @@ -3612,6 +3645,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, | |||
| 3612 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, | 3645 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, |
| 3613 | "2718 Clear Virtual Link Received for VPI 0x%x" | 3646 | "2718 Clear Virtual Link Received for VPI 0x%x" |
| 3614 | " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); | 3647 | " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); |
| 3648 | |||
| 3615 | vport = lpfc_find_vport_by_vpid(phba, | 3649 | vport = lpfc_find_vport_by_vpid(phba, |
| 3616 | acqe_fip->index - phba->vpi_base); | 3650 | acqe_fip->index - phba->vpi_base); |
| 3617 | ndlp = lpfc_sli4_perform_vport_cvl(vport); | 3651 | ndlp = lpfc_sli4_perform_vport_cvl(vport); |
| @@ -3935,6 +3969,10 @@ lpfc_enable_pci_dev(struct lpfc_hba *phba) | |||
| 3935 | pci_try_set_mwi(pdev); | 3969 | pci_try_set_mwi(pdev); |
| 3936 | pci_save_state(pdev); | 3970 | pci_save_state(pdev); |
| 3937 | 3971 | ||
| 3972 | /* PCIe EEH recovery on powerpc platforms needs fundamental reset */ | ||
| 3973 | if (pci_find_capability(pdev, PCI_CAP_ID_EXP)) | ||
| 3974 | pdev->needs_freset = 1; | ||
| 3975 | |||
| 3938 | return 0; | 3976 | return 0; |
| 3939 | 3977 | ||
| 3940 | out_disable_device: | 3978 | out_disable_device: |
| @@ -3997,6 +4035,36 @@ lpfc_reset_hba(struct lpfc_hba *phba) | |||
| 3997 | } | 4035 | } |
| 3998 | 4036 | ||
| 3999 | /** | 4037 | /** |
| 4038 | * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions | ||
| 4039 | * @phba: pointer to lpfc hba data structure. | ||
| 4040 | * @nr_vfn: number of virtual functions to be enabled. | ||
| 4041 | * | ||
| 4042 | * This function enables the PCI SR-IOV virtual functions to a physical | ||
| 4043 | * function. It invokes the PCI SR-IOV api with the @nr_vfn provided to | ||
| 4044 | * enable the number of virtual functions to the physical function. As | ||
| 4045 | * not all devices support SR-IOV, the return code from the pci_enable_sriov() | ||
| 4046 | * API call does not considered as an error condition for most of the device. | ||
| 4047 | **/ | ||
| 4048 | int | ||
| 4049 | lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn) | ||
| 4050 | { | ||
| 4051 | struct pci_dev *pdev = phba->pcidev; | ||
| 4052 | int rc; | ||
| 4053 | |||
| 4054 | rc = pci_enable_sriov(pdev, nr_vfn); | ||
| 4055 | if (rc) { | ||
| 4056 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 4057 | "2806 Failed to enable sriov on this device " | ||
| 4058 | "with vfn number nr_vf:%d, rc:%d\n", | ||
| 4059 | nr_vfn, rc); | ||
| 4060 | } else | ||
| 4061 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 4062 | "2807 Successful enable sriov on this device " | ||
| 4063 | "with vfn number nr_vf:%d\n", nr_vfn); | ||
| 4064 | return rc; | ||
| 4065 | } | ||
| 4066 | |||
| 4067 | /** | ||
| 4000 | * lpfc_sli_driver_resource_setup - Setup driver internal resources for SLI3 dev. | 4068 | * lpfc_sli_driver_resource_setup - Setup driver internal resources for SLI3 dev. |
| 4001 | * @phba: pointer to lpfc hba data structure. | 4069 | * @phba: pointer to lpfc hba data structure. |
| 4002 | * | 4070 | * |
| @@ -4011,6 +4079,7 @@ static int | |||
| 4011 | lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | 4079 | lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) |
| 4012 | { | 4080 | { |
| 4013 | struct lpfc_sli *psli; | 4081 | struct lpfc_sli *psli; |
| 4082 | int rc; | ||
| 4014 | 4083 | ||
| 4015 | /* | 4084 | /* |
| 4016 | * Initialize timers used by driver | 4085 | * Initialize timers used by driver |
| @@ -4085,6 +4154,23 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4085 | if (lpfc_mem_alloc(phba, BPL_ALIGN_SZ)) | 4154 | if (lpfc_mem_alloc(phba, BPL_ALIGN_SZ)) |
| 4086 | return -ENOMEM; | 4155 | return -ENOMEM; |
| 4087 | 4156 | ||
| 4157 | /* | ||
| 4158 | * Enable sr-iov virtual functions if supported and configured | ||
| 4159 | * through the module parameter. | ||
| 4160 | */ | ||
| 4161 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
| 4162 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, | ||
| 4163 | phba->cfg_sriov_nr_virtfn); | ||
| 4164 | if (rc) { | ||
| 4165 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 4166 | "2808 Requested number of SR-IOV " | ||
| 4167 | "virtual functions (%d) is not " | ||
| 4168 | "supported\n", | ||
| 4169 | phba->cfg_sriov_nr_virtfn); | ||
| 4170 | phba->cfg_sriov_nr_virtfn = 0; | ||
| 4171 | } | ||
| 4172 | } | ||
| 4173 | |||
| 4088 | return 0; | 4174 | return 0; |
| 4089 | } | 4175 | } |
| 4090 | 4176 | ||
| @@ -4161,6 +4247,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4161 | phba->fcf.redisc_wait.data = (unsigned long)phba; | 4247 | phba->fcf.redisc_wait.data = (unsigned long)phba; |
| 4162 | 4248 | ||
| 4163 | /* | 4249 | /* |
| 4250 | * Control structure for handling external multi-buffer mailbox | ||
| 4251 | * command pass-through. | ||
| 4252 | */ | ||
| 4253 | memset((uint8_t *)&phba->mbox_ext_buf_ctx, 0, | ||
| 4254 | sizeof(struct lpfc_mbox_ext_buf_ctx)); | ||
| 4255 | INIT_LIST_HEAD(&phba->mbox_ext_buf_ctx.ext_dmabuf_list); | ||
| 4256 | |||
| 4257 | /* | ||
| 4164 | * We need to do a READ_CONFIG mailbox command here before | 4258 | * We need to do a READ_CONFIG mailbox command here before |
| 4165 | * calling lpfc_get_cfgparam. For VFs this will report the | 4259 | * calling lpfc_get_cfgparam. For VFs this will report the |
| 4166 | * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings. | 4260 | * MAX_XRI, MAX_VPI, MAX_RPI, MAX_IOCB, and MAX_VFI settings. |
| @@ -4233,7 +4327,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4233 | spin_lock_init(&phba->sli4_hba.abts_sgl_list_lock); | 4327 | spin_lock_init(&phba->sli4_hba.abts_sgl_list_lock); |
| 4234 | 4328 | ||
| 4235 | /* | 4329 | /* |
| 4236 | * Initialize dirver internal slow-path work queues | 4330 | * Initialize driver internal slow-path work queues |
| 4237 | */ | 4331 | */ |
| 4238 | 4332 | ||
| 4239 | /* Driver internel slow-path CQ Event pool */ | 4333 | /* Driver internel slow-path CQ Event pool */ |
| @@ -4249,6 +4343,12 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4249 | /* Receive queue CQ Event work queue list */ | 4343 | /* Receive queue CQ Event work queue list */ |
| 4250 | INIT_LIST_HEAD(&phba->sli4_hba.sp_unsol_work_queue); | 4344 | INIT_LIST_HEAD(&phba->sli4_hba.sp_unsol_work_queue); |
| 4251 | 4345 | ||
| 4346 | /* Initialize extent block lists. */ | ||
| 4347 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_blk_list); | ||
| 4348 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_xri_blk_list); | ||
| 4349 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_vfi_blk_list); | ||
| 4350 | INIT_LIST_HEAD(&phba->lpfc_vpi_blk_list); | ||
| 4351 | |||
| 4252 | /* Initialize the driver internal SLI layer lists. */ | 4352 | /* Initialize the driver internal SLI layer lists. */ |
| 4253 | lpfc_sli_setup(phba); | 4353 | lpfc_sli_setup(phba); |
| 4254 | lpfc_sli_queue_setup(phba); | 4354 | lpfc_sli_queue_setup(phba); |
| @@ -4323,9 +4423,19 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4323 | } | 4423 | } |
| 4324 | /* | 4424 | /* |
| 4325 | * Get sli4 parameters that override parameters from Port capabilities. | 4425 | * Get sli4 parameters that override parameters from Port capabilities. |
| 4326 | * If this call fails it is not a critical error so continue loading. | 4426 | * If this call fails, it isn't critical unless the SLI4 parameters come |
| 4427 | * back in conflict. | ||
| 4327 | */ | 4428 | */ |
| 4328 | lpfc_get_sli4_parameters(phba, mboxq); | 4429 | rc = lpfc_get_sli4_parameters(phba, mboxq); |
| 4430 | if (rc) { | ||
| 4431 | if (phba->sli4_hba.extents_in_use && | ||
| 4432 | phba->sli4_hba.rpi_hdrs_in_use) { | ||
| 4433 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 4434 | "2999 Unsupported SLI4 Parameters " | ||
| 4435 | "Extents and RPI headers enabled.\n"); | ||
| 4436 | goto out_free_bsmbx; | ||
| 4437 | } | ||
| 4438 | } | ||
| 4329 | mempool_free(mboxq, phba->mbox_mem_pool); | 4439 | mempool_free(mboxq, phba->mbox_mem_pool); |
| 4330 | /* Create all the SLI4 queues */ | 4440 | /* Create all the SLI4 queues */ |
| 4331 | rc = lpfc_sli4_queue_create(phba); | 4441 | rc = lpfc_sli4_queue_create(phba); |
| @@ -4350,7 +4460,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4350 | "1430 Failed to initialize sgl list.\n"); | 4460 | "1430 Failed to initialize sgl list.\n"); |
| 4351 | goto out_free_sgl_list; | 4461 | goto out_free_sgl_list; |
| 4352 | } | 4462 | } |
| 4353 | |||
| 4354 | rc = lpfc_sli4_init_rpi_hdrs(phba); | 4463 | rc = lpfc_sli4_init_rpi_hdrs(phba); |
| 4355 | if (rc) { | 4464 | if (rc) { |
| 4356 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4465 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| @@ -4366,6 +4475,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4366 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4475 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 4367 | "2759 Failed allocate memory for FCF round " | 4476 | "2759 Failed allocate memory for FCF round " |
| 4368 | "robin failover bmask\n"); | 4477 | "robin failover bmask\n"); |
| 4478 | rc = -ENOMEM; | ||
| 4369 | goto out_remove_rpi_hdrs; | 4479 | goto out_remove_rpi_hdrs; |
| 4370 | } | 4480 | } |
| 4371 | 4481 | ||
| @@ -4375,6 +4485,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4375 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4485 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 4376 | "2572 Failed allocate memory for fast-path " | 4486 | "2572 Failed allocate memory for fast-path " |
| 4377 | "per-EQ handle array\n"); | 4487 | "per-EQ handle array\n"); |
| 4488 | rc = -ENOMEM; | ||
| 4378 | goto out_free_fcf_rr_bmask; | 4489 | goto out_free_fcf_rr_bmask; |
| 4379 | } | 4490 | } |
| 4380 | 4491 | ||
| @@ -4384,9 +4495,27 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4384 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4495 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 4385 | "2573 Failed allocate memory for msi-x " | 4496 | "2573 Failed allocate memory for msi-x " |
| 4386 | "interrupt vector entries\n"); | 4497 | "interrupt vector entries\n"); |
| 4498 | rc = -ENOMEM; | ||
| 4387 | goto out_free_fcp_eq_hdl; | 4499 | goto out_free_fcp_eq_hdl; |
| 4388 | } | 4500 | } |
| 4389 | 4501 | ||
| 4502 | /* | ||
| 4503 | * Enable sr-iov virtual functions if supported and configured | ||
| 4504 | * through the module parameter. | ||
| 4505 | */ | ||
| 4506 | if (phba->cfg_sriov_nr_virtfn > 0) { | ||
| 4507 | rc = lpfc_sli_probe_sriov_nr_virtfn(phba, | ||
| 4508 | phba->cfg_sriov_nr_virtfn); | ||
| 4509 | if (rc) { | ||
| 4510 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 4511 | "3020 Requested number of SR-IOV " | ||
| 4512 | "virtual functions (%d) is not " | ||
| 4513 | "supported\n", | ||
| 4514 | phba->cfg_sriov_nr_virtfn); | ||
| 4515 | phba->cfg_sriov_nr_virtfn = 0; | ||
| 4516 | } | ||
| 4517 | } | ||
| 4518 | |||
| 4390 | return rc; | 4519 | return rc; |
| 4391 | 4520 | ||
| 4392 | out_free_fcp_eq_hdl: | 4521 | out_free_fcp_eq_hdl: |
| @@ -4449,6 +4578,9 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) | |||
| 4449 | lpfc_sli4_cq_event_release_all(phba); | 4578 | lpfc_sli4_cq_event_release_all(phba); |
| 4450 | lpfc_sli4_cq_event_pool_destroy(phba); | 4579 | lpfc_sli4_cq_event_pool_destroy(phba); |
| 4451 | 4580 | ||
| 4581 | /* Release resource identifiers. */ | ||
| 4582 | lpfc_sli4_dealloc_resource_identifiers(phba); | ||
| 4583 | |||
| 4452 | /* Free the bsmbx region. */ | 4584 | /* Free the bsmbx region. */ |
| 4453 | lpfc_destroy_bootstrap_mbox(phba); | 4585 | lpfc_destroy_bootstrap_mbox(phba); |
| 4454 | 4586 | ||
| @@ -4649,6 +4781,7 @@ lpfc_init_iocb_list(struct lpfc_hba *phba, int iocb_count) | |||
| 4649 | "Unloading driver.\n", __func__); | 4781 | "Unloading driver.\n", __func__); |
| 4650 | goto out_free_iocbq; | 4782 | goto out_free_iocbq; |
| 4651 | } | 4783 | } |
| 4784 | iocbq_entry->sli4_lxritag = NO_XRI; | ||
| 4652 | iocbq_entry->sli4_xritag = NO_XRI; | 4785 | iocbq_entry->sli4_xritag = NO_XRI; |
| 4653 | 4786 | ||
| 4654 | spin_lock_irq(&phba->hbalock); | 4787 | spin_lock_irq(&phba->hbalock); |
| @@ -4746,7 +4879,7 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
| 4746 | 4879 | ||
| 4747 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); | 4880 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); |
| 4748 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 4881 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
| 4749 | "2400 lpfc_init_sgl_list els %d.\n", | 4882 | "2400 ELS XRI count %d.\n", |
| 4750 | els_xri_cnt); | 4883 | els_xri_cnt); |
| 4751 | /* Initialize and populate the sglq list per host/VF. */ | 4884 | /* Initialize and populate the sglq list per host/VF. */ |
| 4752 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list); | 4885 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list); |
| @@ -4779,7 +4912,6 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
| 4779 | phba->sli4_hba.scsi_xri_max = | 4912 | phba->sli4_hba.scsi_xri_max = |
| 4780 | phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt; | 4913 | phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt; |
| 4781 | phba->sli4_hba.scsi_xri_cnt = 0; | 4914 | phba->sli4_hba.scsi_xri_cnt = 0; |
| 4782 | |||
| 4783 | phba->sli4_hba.lpfc_scsi_psb_array = | 4915 | phba->sli4_hba.lpfc_scsi_psb_array = |
| 4784 | kzalloc((sizeof(struct lpfc_scsi_buf *) * | 4916 | kzalloc((sizeof(struct lpfc_scsi_buf *) * |
| 4785 | phba->sli4_hba.scsi_xri_max), GFP_KERNEL); | 4917 | phba->sli4_hba.scsi_xri_max), GFP_KERNEL); |
| @@ -4802,13 +4934,6 @@ lpfc_init_sgl_list(struct lpfc_hba *phba) | |||
| 4802 | goto out_free_mem; | 4934 | goto out_free_mem; |
| 4803 | } | 4935 | } |
| 4804 | 4936 | ||
| 4805 | sglq_entry->sli4_xritag = lpfc_sli4_next_xritag(phba); | ||
| 4806 | if (sglq_entry->sli4_xritag == NO_XRI) { | ||
| 4807 | kfree(sglq_entry); | ||
| 4808 | printk(KERN_ERR "%s: failed to allocate XRI.\n" | ||
| 4809 | "Unloading driver.\n", __func__); | ||
| 4810 | goto out_free_mem; | ||
| 4811 | } | ||
| 4812 | sglq_entry->buff_type = GEN_BUFF_TYPE; | 4937 | sglq_entry->buff_type = GEN_BUFF_TYPE; |
| 4813 | sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys); | 4938 | sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys); |
| 4814 | if (sglq_entry->virt == NULL) { | 4939 | if (sglq_entry->virt == NULL) { |
| @@ -4857,24 +4982,20 @@ int | |||
| 4857 | lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) | 4982 | lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) |
| 4858 | { | 4983 | { |
| 4859 | int rc = 0; | 4984 | int rc = 0; |
| 4860 | int longs; | ||
| 4861 | uint16_t rpi_count; | ||
| 4862 | struct lpfc_rpi_hdr *rpi_hdr; | 4985 | struct lpfc_rpi_hdr *rpi_hdr; |
| 4863 | 4986 | ||
| 4864 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list); | 4987 | INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list); |
| 4865 | |||
| 4866 | /* | 4988 | /* |
| 4867 | * Provision an rpi bitmask range for discovery. The total count | 4989 | * If the SLI4 port supports extents, posting the rpi header isn't |
| 4868 | * is the difference between max and base + 1. | 4990 | * required. Set the expected maximum count and let the actual value |
| 4991 | * get set when extents are fully allocated. | ||
| 4869 | */ | 4992 | */ |
| 4870 | rpi_count = phba->sli4_hba.max_cfg_param.rpi_base + | 4993 | if (!phba->sli4_hba.rpi_hdrs_in_use) { |
| 4871 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | 4994 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi; |
| 4872 | 4995 | return rc; | |
| 4873 | longs = ((rpi_count) + BITS_PER_LONG - 1) / BITS_PER_LONG; | 4996 | } |
| 4874 | phba->sli4_hba.rpi_bmask = kzalloc(longs * sizeof(unsigned long), | 4997 | if (phba->sli4_hba.extents_in_use) |
| 4875 | GFP_KERNEL); | 4998 | return -EIO; |
| 4876 | if (!phba->sli4_hba.rpi_bmask) | ||
| 4877 | return -ENOMEM; | ||
| 4878 | 4999 | ||
| 4879 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | 5000 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); |
| 4880 | if (!rpi_hdr) { | 5001 | if (!rpi_hdr) { |
| @@ -4908,11 +5029,28 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
| 4908 | struct lpfc_rpi_hdr *rpi_hdr; | 5029 | struct lpfc_rpi_hdr *rpi_hdr; |
| 4909 | uint32_t rpi_count; | 5030 | uint32_t rpi_count; |
| 4910 | 5031 | ||
| 5032 | /* | ||
| 5033 | * If the SLI4 port supports extents, posting the rpi header isn't | ||
| 5034 | * required. Set the expected maximum count and let the actual value | ||
| 5035 | * get set when extents are fully allocated. | ||
| 5036 | */ | ||
| 5037 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
| 5038 | return NULL; | ||
| 5039 | if (phba->sli4_hba.extents_in_use) | ||
| 5040 | return NULL; | ||
| 5041 | |||
| 5042 | /* The limit on the logical index is just the max_rpi count. */ | ||
| 4911 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + | 5043 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + |
| 4912 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | 5044 | phba->sli4_hba.max_cfg_param.max_rpi - 1; |
| 4913 | 5045 | ||
| 4914 | spin_lock_irq(&phba->hbalock); | 5046 | spin_lock_irq(&phba->hbalock); |
| 4915 | curr_rpi_range = phba->sli4_hba.next_rpi; | 5047 | /* |
| 5048 | * Establish the starting RPI in this header block. The starting | ||
| 5049 | * rpi is normalized to a zero base because the physical rpi is | ||
| 5050 | * port based. | ||
| 5051 | */ | ||
| 5052 | curr_rpi_range = phba->sli4_hba.next_rpi - | ||
| 5053 | phba->sli4_hba.max_cfg_param.rpi_base; | ||
| 4916 | spin_unlock_irq(&phba->hbalock); | 5054 | spin_unlock_irq(&phba->hbalock); |
| 4917 | 5055 | ||
| 4918 | /* | 5056 | /* |
| @@ -4925,6 +5063,8 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
| 4925 | else | 5063 | else |
| 4926 | rpi_count = LPFC_RPI_HDR_COUNT; | 5064 | rpi_count = LPFC_RPI_HDR_COUNT; |
| 4927 | 5065 | ||
| 5066 | if (!rpi_count) | ||
| 5067 | return NULL; | ||
| 4928 | /* | 5068 | /* |
| 4929 | * First allocate the protocol header region for the port. The | 5069 | * First allocate the protocol header region for the port. The |
| 4930 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. | 5070 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. |
| @@ -4957,12 +5097,14 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
| 4957 | rpi_hdr->len = LPFC_HDR_TEMPLATE_SIZE; | 5097 | rpi_hdr->len = LPFC_HDR_TEMPLATE_SIZE; |
| 4958 | rpi_hdr->page_count = 1; | 5098 | rpi_hdr->page_count = 1; |
| 4959 | spin_lock_irq(&phba->hbalock); | 5099 | spin_lock_irq(&phba->hbalock); |
| 4960 | rpi_hdr->start_rpi = phba->sli4_hba.next_rpi; | 5100 | |
| 5101 | /* The rpi_hdr stores the logical index only. */ | ||
| 5102 | rpi_hdr->start_rpi = curr_rpi_range; | ||
| 4961 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); | 5103 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); |
| 4962 | 5104 | ||
| 4963 | /* | 5105 | /* |
| 4964 | * The next_rpi stores the next module-64 rpi value to post | 5106 | * The next_rpi stores the next logical module-64 rpi value used |
| 4965 | * in any subsequent rpi memory region postings. | 5107 | * to post physical rpis in subsequent rpi postings. |
| 4966 | */ | 5108 | */ |
| 4967 | phba->sli4_hba.next_rpi += rpi_count; | 5109 | phba->sli4_hba.next_rpi += rpi_count; |
| 4968 | spin_unlock_irq(&phba->hbalock); | 5110 | spin_unlock_irq(&phba->hbalock); |
| @@ -4981,15 +5123,18 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
| 4981 | * @phba: pointer to lpfc hba data structure. | 5123 | * @phba: pointer to lpfc hba data structure. |
| 4982 | * | 5124 | * |
| 4983 | * This routine is invoked to remove all memory resources allocated | 5125 | * This routine is invoked to remove all memory resources allocated |
| 4984 | * to support rpis. This routine presumes the caller has released all | 5126 | * to support rpis for SLI4 ports not supporting extents. This routine |
| 4985 | * rpis consumed by fabric or port logins and is prepared to have | 5127 | * presumes the caller has released all rpis consumed by fabric or port |
| 4986 | * the header pages removed. | 5128 | * logins and is prepared to have the header pages removed. |
| 4987 | **/ | 5129 | **/ |
| 4988 | void | 5130 | void |
| 4989 | lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) | 5131 | lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) |
| 4990 | { | 5132 | { |
| 4991 | struct lpfc_rpi_hdr *rpi_hdr, *next_rpi_hdr; | 5133 | struct lpfc_rpi_hdr *rpi_hdr, *next_rpi_hdr; |
| 4992 | 5134 | ||
| 5135 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
| 5136 | goto exit; | ||
| 5137 | |||
| 4993 | list_for_each_entry_safe(rpi_hdr, next_rpi_hdr, | 5138 | list_for_each_entry_safe(rpi_hdr, next_rpi_hdr, |
| 4994 | &phba->sli4_hba.lpfc_rpi_hdr_list, list) { | 5139 | &phba->sli4_hba.lpfc_rpi_hdr_list, list) { |
| 4995 | list_del(&rpi_hdr->list); | 5140 | list_del(&rpi_hdr->list); |
| @@ -4998,9 +5143,9 @@ lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba) | |||
| 4998 | kfree(rpi_hdr->dmabuf); | 5143 | kfree(rpi_hdr->dmabuf); |
| 4999 | kfree(rpi_hdr); | 5144 | kfree(rpi_hdr); |
| 5000 | } | 5145 | } |
| 5001 | 5146 | exit: | |
| 5002 | phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.rpi_base; | 5147 | /* There are no rpis available to the port now. */ |
| 5003 | memset(phba->sli4_hba.rpi_bmask, 0, sizeof(*phba->sli4_hba.rpi_bmask)); | 5148 | phba->sli4_hba.next_rpi = 0; |
| 5004 | } | 5149 | } |
| 5005 | 5150 | ||
| 5006 | /** | 5151 | /** |
| @@ -5487,7 +5632,8 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) | |||
| 5487 | /* Final checks. The port status should be clean. */ | 5632 | /* Final checks. The port status should be clean. */ |
| 5488 | if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, | 5633 | if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, |
| 5489 | ®_data.word0) || | 5634 | ®_data.word0) || |
| 5490 | bf_get(lpfc_sliport_status_err, ®_data)) { | 5635 | (bf_get(lpfc_sliport_status_err, ®_data) && |
| 5636 | !bf_get(lpfc_sliport_status_rn, ®_data))) { | ||
| 5491 | phba->work_status[0] = | 5637 | phba->work_status[0] = |
| 5492 | readl(phba->sli4_hba.u.if_type2. | 5638 | readl(phba->sli4_hba.u.if_type2. |
| 5493 | ERR1regaddr); | 5639 | ERR1regaddr); |
| @@ -5741,7 +5887,12 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5741 | { | 5887 | { |
| 5742 | LPFC_MBOXQ_t *pmb; | 5888 | LPFC_MBOXQ_t *pmb; |
| 5743 | struct lpfc_mbx_read_config *rd_config; | 5889 | struct lpfc_mbx_read_config *rd_config; |
| 5744 | uint32_t rc = 0; | 5890 | union lpfc_sli4_cfg_shdr *shdr; |
| 5891 | uint32_t shdr_status, shdr_add_status; | ||
| 5892 | struct lpfc_mbx_get_func_cfg *get_func_cfg; | ||
| 5893 | struct lpfc_rsrc_desc_fcfcoe *desc; | ||
| 5894 | uint32_t desc_count; | ||
| 5895 | int length, i, rc = 0; | ||
| 5745 | 5896 | ||
| 5746 | pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 5897 | pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 5747 | if (!pmb) { | 5898 | if (!pmb) { |
| @@ -5763,6 +5914,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5763 | rc = -EIO; | 5914 | rc = -EIO; |
| 5764 | } else { | 5915 | } else { |
| 5765 | rd_config = &pmb->u.mqe.un.rd_config; | 5916 | rd_config = &pmb->u.mqe.un.rd_config; |
| 5917 | phba->sli4_hba.extents_in_use = | ||
| 5918 | bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config); | ||
| 5766 | phba->sli4_hba.max_cfg_param.max_xri = | 5919 | phba->sli4_hba.max_cfg_param.max_xri = |
| 5767 | bf_get(lpfc_mbx_rd_conf_xri_count, rd_config); | 5920 | bf_get(lpfc_mbx_rd_conf_xri_count, rd_config); |
| 5768 | phba->sli4_hba.max_cfg_param.xri_base = | 5921 | phba->sli4_hba.max_cfg_param.xri_base = |
| @@ -5781,8 +5934,6 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5781 | bf_get(lpfc_mbx_rd_conf_vfi_base, rd_config); | 5934 | bf_get(lpfc_mbx_rd_conf_vfi_base, rd_config); |
| 5782 | phba->sli4_hba.max_cfg_param.max_fcfi = | 5935 | phba->sli4_hba.max_cfg_param.max_fcfi = |
| 5783 | bf_get(lpfc_mbx_rd_conf_fcfi_count, rd_config); | 5936 | bf_get(lpfc_mbx_rd_conf_fcfi_count, rd_config); |
| 5784 | phba->sli4_hba.max_cfg_param.fcfi_base = | ||
| 5785 | bf_get(lpfc_mbx_rd_conf_fcfi_base, rd_config); | ||
| 5786 | phba->sli4_hba.max_cfg_param.max_eq = | 5937 | phba->sli4_hba.max_cfg_param.max_eq = |
| 5787 | bf_get(lpfc_mbx_rd_conf_eq_count, rd_config); | 5938 | bf_get(lpfc_mbx_rd_conf_eq_count, rd_config); |
| 5788 | phba->sli4_hba.max_cfg_param.max_rq = | 5939 | phba->sli4_hba.max_cfg_param.max_rq = |
| @@ -5800,11 +5951,13 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5800 | (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0; | 5951 | (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0; |
| 5801 | phba->max_vports = phba->max_vpi; | 5952 | phba->max_vports = phba->max_vpi; |
| 5802 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 5953 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
| 5803 | "2003 cfg params XRI(B:%d M:%d), " | 5954 | "2003 cfg params Extents? %d " |
| 5955 | "XRI(B:%d M:%d), " | ||
| 5804 | "VPI(B:%d M:%d) " | 5956 | "VPI(B:%d M:%d) " |
| 5805 | "VFI(B:%d M:%d) " | 5957 | "VFI(B:%d M:%d) " |
| 5806 | "RPI(B:%d M:%d) " | 5958 | "RPI(B:%d M:%d) " |
| 5807 | "FCFI(B:%d M:%d)\n", | 5959 | "FCFI(Count:%d)\n", |
| 5960 | phba->sli4_hba.extents_in_use, | ||
| 5808 | phba->sli4_hba.max_cfg_param.xri_base, | 5961 | phba->sli4_hba.max_cfg_param.xri_base, |
| 5809 | phba->sli4_hba.max_cfg_param.max_xri, | 5962 | phba->sli4_hba.max_cfg_param.max_xri, |
| 5810 | phba->sli4_hba.max_cfg_param.vpi_base, | 5963 | phba->sli4_hba.max_cfg_param.vpi_base, |
| @@ -5813,10 +5966,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5813 | phba->sli4_hba.max_cfg_param.max_vfi, | 5966 | phba->sli4_hba.max_cfg_param.max_vfi, |
| 5814 | phba->sli4_hba.max_cfg_param.rpi_base, | 5967 | phba->sli4_hba.max_cfg_param.rpi_base, |
| 5815 | phba->sli4_hba.max_cfg_param.max_rpi, | 5968 | phba->sli4_hba.max_cfg_param.max_rpi, |
| 5816 | phba->sli4_hba.max_cfg_param.fcfi_base, | ||
| 5817 | phba->sli4_hba.max_cfg_param.max_fcfi); | 5969 | phba->sli4_hba.max_cfg_param.max_fcfi); |
| 5818 | } | 5970 | } |
| 5819 | mempool_free(pmb, phba->mbox_mem_pool); | 5971 | |
| 5972 | if (rc) | ||
| 5973 | goto read_cfg_out; | ||
| 5820 | 5974 | ||
| 5821 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ | 5975 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ |
| 5822 | if (phba->cfg_hba_queue_depth > | 5976 | if (phba->cfg_hba_queue_depth > |
| @@ -5825,6 +5979,65 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) | |||
| 5825 | phba->cfg_hba_queue_depth = | 5979 | phba->cfg_hba_queue_depth = |
| 5826 | phba->sli4_hba.max_cfg_param.max_xri - | 5980 | phba->sli4_hba.max_cfg_param.max_xri - |
| 5827 | lpfc_sli4_get_els_iocb_cnt(phba); | 5981 | lpfc_sli4_get_els_iocb_cnt(phba); |
| 5982 | |||
| 5983 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | ||
| 5984 | LPFC_SLI_INTF_IF_TYPE_2) | ||
| 5985 | goto read_cfg_out; | ||
| 5986 | |||
| 5987 | /* get the pf# and vf# for SLI4 if_type 2 port */ | ||
| 5988 | length = (sizeof(struct lpfc_mbx_get_func_cfg) - | ||
| 5989 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 5990 | lpfc_sli4_config(phba, pmb, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 5991 | LPFC_MBOX_OPCODE_GET_FUNCTION_CONFIG, | ||
| 5992 | length, LPFC_SLI4_MBX_EMBED); | ||
| 5993 | |||
| 5994 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | ||
| 5995 | shdr = (union lpfc_sli4_cfg_shdr *) | ||
| 5996 | &pmb->u.mqe.un.sli4_config.header.cfg_shdr; | ||
| 5997 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 5998 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
| 5999 | if (rc || shdr_status || shdr_add_status) { | ||
| 6000 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
| 6001 | "3026 Mailbox failed , mbxCmd x%x " | ||
| 6002 | "GET_FUNCTION_CONFIG, mbxStatus x%x\n", | ||
| 6003 | bf_get(lpfc_mqe_command, &pmb->u.mqe), | ||
| 6004 | bf_get(lpfc_mqe_status, &pmb->u.mqe)); | ||
| 6005 | rc = -EIO; | ||
| 6006 | goto read_cfg_out; | ||
| 6007 | } | ||
| 6008 | |||
| 6009 | /* search for fc_fcoe resrouce descriptor */ | ||
| 6010 | get_func_cfg = &pmb->u.mqe.un.get_func_cfg; | ||
| 6011 | desc_count = get_func_cfg->func_cfg.rsrc_desc_count; | ||
| 6012 | |||
| 6013 | for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) { | ||
| 6014 | desc = (struct lpfc_rsrc_desc_fcfcoe *) | ||
| 6015 | &get_func_cfg->func_cfg.desc[i]; | ||
| 6016 | if (LPFC_RSRC_DESC_TYPE_FCFCOE == | ||
| 6017 | bf_get(lpfc_rsrc_desc_pcie_type, desc)) { | ||
| 6018 | phba->sli4_hba.iov.pf_number = | ||
| 6019 | bf_get(lpfc_rsrc_desc_fcfcoe_pfnum, desc); | ||
| 6020 | phba->sli4_hba.iov.vf_number = | ||
| 6021 | bf_get(lpfc_rsrc_desc_fcfcoe_vfnum, desc); | ||
| 6022 | break; | ||
| 6023 | } | ||
| 6024 | } | ||
| 6025 | |||
| 6026 | if (i < LPFC_RSRC_DESC_MAX_NUM) | ||
| 6027 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
| 6028 | "3027 GET_FUNCTION_CONFIG: pf_number:%d, " | ||
| 6029 | "vf_number:%d\n", phba->sli4_hba.iov.pf_number, | ||
| 6030 | phba->sli4_hba.iov.vf_number); | ||
| 6031 | else { | ||
| 6032 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
| 6033 | "3028 GET_FUNCTION_CONFIG: failed to find " | ||
| 6034 | "Resrouce Descriptor:x%x\n", | ||
| 6035 | LPFC_RSRC_DESC_TYPE_FCFCOE); | ||
| 6036 | rc = -EIO; | ||
| 6037 | } | ||
| 6038 | |||
| 6039 | read_cfg_out: | ||
| 6040 | mempool_free(pmb, phba->mbox_mem_pool); | ||
| 5828 | return rc; | 6041 | return rc; |
| 5829 | } | 6042 | } |
| 5830 | 6043 | ||
| @@ -6229,8 +6442,10 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) | |||
| 6229 | phba->sli4_hba.mbx_cq = NULL; | 6442 | phba->sli4_hba.mbx_cq = NULL; |
| 6230 | 6443 | ||
| 6231 | /* Release FCP response complete queue */ | 6444 | /* Release FCP response complete queue */ |
| 6232 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) | 6445 | fcp_qidx = 0; |
| 6446 | do | ||
| 6233 | lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); | 6447 | lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); |
| 6448 | while (++fcp_qidx < phba->cfg_fcp_eq_count); | ||
| 6234 | kfree(phba->sli4_hba.fcp_cq); | 6449 | kfree(phba->sli4_hba.fcp_cq); |
| 6235 | phba->sli4_hba.fcp_cq = NULL; | 6450 | phba->sli4_hba.fcp_cq = NULL; |
| 6236 | 6451 | ||
| @@ -6353,16 +6568,24 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
| 6353 | phba->sli4_hba.sp_eq->queue_id); | 6568 | phba->sli4_hba.sp_eq->queue_id); |
| 6354 | 6569 | ||
| 6355 | /* Set up fast-path FCP Response Complete Queue */ | 6570 | /* Set up fast-path FCP Response Complete Queue */ |
| 6356 | for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) { | 6571 | fcp_cqidx = 0; |
| 6572 | do { | ||
| 6357 | if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) { | 6573 | if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) { |
| 6358 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 6574 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 6359 | "0526 Fast-path FCP CQ (%d) not " | 6575 | "0526 Fast-path FCP CQ (%d) not " |
| 6360 | "allocated\n", fcp_cqidx); | 6576 | "allocated\n", fcp_cqidx); |
| 6361 | goto out_destroy_fcp_cq; | 6577 | goto out_destroy_fcp_cq; |
| 6362 | } | 6578 | } |
| 6363 | rc = lpfc_cq_create(phba, phba->sli4_hba.fcp_cq[fcp_cqidx], | 6579 | if (phba->cfg_fcp_eq_count) |
| 6364 | phba->sli4_hba.fp_eq[fcp_cqidx], | 6580 | rc = lpfc_cq_create(phba, |
| 6365 | LPFC_WCQ, LPFC_FCP); | 6581 | phba->sli4_hba.fcp_cq[fcp_cqidx], |
| 6582 | phba->sli4_hba.fp_eq[fcp_cqidx], | ||
| 6583 | LPFC_WCQ, LPFC_FCP); | ||
| 6584 | else | ||
| 6585 | rc = lpfc_cq_create(phba, | ||
| 6586 | phba->sli4_hba.fcp_cq[fcp_cqidx], | ||
| 6587 | phba->sli4_hba.sp_eq, | ||
| 6588 | LPFC_WCQ, LPFC_FCP); | ||
| 6366 | if (rc) { | 6589 | if (rc) { |
| 6367 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 6590 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| 6368 | "0527 Failed setup of fast-path FCP " | 6591 | "0527 Failed setup of fast-path FCP " |
| @@ -6371,12 +6594,15 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
| 6371 | } | 6594 | } |
| 6372 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 6595 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 6373 | "2588 FCP CQ setup: cq[%d]-id=%d, " | 6596 | "2588 FCP CQ setup: cq[%d]-id=%d, " |
| 6374 | "parent eq[%d]-id=%d\n", | 6597 | "parent %seq[%d]-id=%d\n", |
| 6375 | fcp_cqidx, | 6598 | fcp_cqidx, |
| 6376 | phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id, | 6599 | phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id, |
| 6600 | (phba->cfg_fcp_eq_count) ? "" : "sp_", | ||
| 6377 | fcp_cqidx, | 6601 | fcp_cqidx, |
| 6378 | phba->sli4_hba.fp_eq[fcp_cqidx]->queue_id); | 6602 | (phba->cfg_fcp_eq_count) ? |
| 6379 | } | 6603 | phba->sli4_hba.fp_eq[fcp_cqidx]->queue_id : |
| 6604 | phba->sli4_hba.sp_eq->queue_id); | ||
| 6605 | } while (++fcp_cqidx < phba->cfg_fcp_eq_count); | ||
| 6380 | 6606 | ||
| 6381 | /* | 6607 | /* |
| 6382 | * Set up all the Work Queues (WQs) | 6608 | * Set up all the Work Queues (WQs) |
| @@ -6445,7 +6671,9 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
| 6445 | fcp_cq_index, | 6671 | fcp_cq_index, |
| 6446 | phba->sli4_hba.fcp_cq[fcp_cq_index]->queue_id); | 6672 | phba->sli4_hba.fcp_cq[fcp_cq_index]->queue_id); |
| 6447 | /* Round robin FCP Work Queue's Completion Queue assignment */ | 6673 | /* Round robin FCP Work Queue's Completion Queue assignment */ |
| 6448 | fcp_cq_index = ((fcp_cq_index + 1) % phba->cfg_fcp_eq_count); | 6674 | if (phba->cfg_fcp_eq_count) |
| 6675 | fcp_cq_index = ((fcp_cq_index + 1) % | ||
| 6676 | phba->cfg_fcp_eq_count); | ||
| 6449 | } | 6677 | } |
| 6450 | 6678 | ||
| 6451 | /* | 6679 | /* |
| @@ -6827,6 +7055,8 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
| 6827 | if (rdy_chk < 1000) | 7055 | if (rdy_chk < 1000) |
| 6828 | break; | 7056 | break; |
| 6829 | } | 7057 | } |
| 7058 | /* delay driver action following IF_TYPE_2 function reset */ | ||
| 7059 | msleep(100); | ||
| 6830 | break; | 7060 | break; |
| 6831 | case LPFC_SLI_INTF_IF_TYPE_1: | 7061 | case LPFC_SLI_INTF_IF_TYPE_1: |
| 6832 | default: | 7062 | default: |
| @@ -7419,11 +7649,15 @@ enable_msix_vectors: | |||
| 7419 | /* | 7649 | /* |
| 7420 | * Assign MSI-X vectors to interrupt handlers | 7650 | * Assign MSI-X vectors to interrupt handlers |
| 7421 | */ | 7651 | */ |
| 7422 | 7652 | if (vectors > 1) | |
| 7423 | /* The first vector must associated to slow-path handler for MQ */ | 7653 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, |
| 7424 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, | 7654 | &lpfc_sli4_sp_intr_handler, IRQF_SHARED, |
| 7425 | &lpfc_sli4_sp_intr_handler, IRQF_SHARED, | 7655 | LPFC_SP_DRIVER_HANDLER_NAME, phba); |
| 7426 | LPFC_SP_DRIVER_HANDLER_NAME, phba); | 7656 | else |
| 7657 | /* All Interrupts need to be handled by one EQ */ | ||
| 7658 | rc = request_irq(phba->sli4_hba.msix_entries[0].vector, | ||
| 7659 | &lpfc_sli4_intr_handler, IRQF_SHARED, | ||
| 7660 | LPFC_DRIVER_NAME, phba); | ||
| 7427 | if (rc) { | 7661 | if (rc) { |
| 7428 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | 7662 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
| 7429 | "0485 MSI-X slow-path request_irq failed " | 7663 | "0485 MSI-X slow-path request_irq failed " |
| @@ -7765,6 +7999,7 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) | |||
| 7765 | { | 7999 | { |
| 7766 | int wait_cnt = 0; | 8000 | int wait_cnt = 0; |
| 7767 | LPFC_MBOXQ_t *mboxq; | 8001 | LPFC_MBOXQ_t *mboxq; |
| 8002 | struct pci_dev *pdev = phba->pcidev; | ||
| 7768 | 8003 | ||
| 7769 | lpfc_stop_hba_timers(phba); | 8004 | lpfc_stop_hba_timers(phba); |
| 7770 | phba->sli4_hba.intr_enable = 0; | 8005 | phba->sli4_hba.intr_enable = 0; |
| @@ -7804,6 +8039,10 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba) | |||
| 7804 | /* Disable PCI subsystem interrupt */ | 8039 | /* Disable PCI subsystem interrupt */ |
| 7805 | lpfc_sli4_disable_intr(phba); | 8040 | lpfc_sli4_disable_intr(phba); |
| 7806 | 8041 | ||
| 8042 | /* Disable SR-IOV if enabled */ | ||
| 8043 | if (phba->cfg_sriov_nr_virtfn) | ||
| 8044 | pci_disable_sriov(pdev); | ||
| 8045 | |||
| 7807 | /* Stop kthread signal shall trigger work_done one more time */ | 8046 | /* Stop kthread signal shall trigger work_done one more time */ |
| 7808 | kthread_stop(phba->worker_thread); | 8047 | kthread_stop(phba->worker_thread); |
| 7809 | 8048 | ||
| @@ -7878,6 +8117,11 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 7878 | sli4_params->hdr_pp_align = bf_get(hdr_pp_align, &mqe->un.sli4_params); | 8117 | sli4_params->hdr_pp_align = bf_get(hdr_pp_align, &mqe->un.sli4_params); |
| 7879 | sli4_params->sgl_pages_max = bf_get(sgl_pages, &mqe->un.sli4_params); | 8118 | sli4_params->sgl_pages_max = bf_get(sgl_pages, &mqe->un.sli4_params); |
| 7880 | sli4_params->sgl_pp_align = bf_get(sgl_pp_align, &mqe->un.sli4_params); | 8119 | sli4_params->sgl_pp_align = bf_get(sgl_pp_align, &mqe->un.sli4_params); |
| 8120 | |||
| 8121 | /* Make sure that sge_supp_len can be handled by the driver */ | ||
| 8122 | if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) | ||
| 8123 | sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; | ||
| 8124 | |||
| 7881 | return rc; | 8125 | return rc; |
| 7882 | } | 8126 | } |
| 7883 | 8127 | ||
| @@ -7902,6 +8146,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 7902 | int length; | 8146 | int length; |
| 7903 | struct lpfc_sli4_parameters *mbx_sli4_parameters; | 8147 | struct lpfc_sli4_parameters *mbx_sli4_parameters; |
| 7904 | 8148 | ||
| 8149 | /* | ||
| 8150 | * By default, the driver assumes the SLI4 port requires RPI | ||
| 8151 | * header postings. The SLI4_PARAM response will correct this | ||
| 8152 | * assumption. | ||
| 8153 | */ | ||
| 8154 | phba->sli4_hba.rpi_hdrs_in_use = 1; | ||
| 8155 | |||
| 7905 | /* Read the port's SLI4 Config Parameters */ | 8156 | /* Read the port's SLI4 Config Parameters */ |
| 7906 | length = (sizeof(struct lpfc_mbx_get_sli4_parameters) - | 8157 | length = (sizeof(struct lpfc_mbx_get_sli4_parameters) - |
| 7907 | sizeof(struct lpfc_sli4_cfg_mhdr)); | 8158 | sizeof(struct lpfc_sli4_cfg_mhdr)); |
| @@ -7938,6 +8189,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 7938 | mbx_sli4_parameters); | 8189 | mbx_sli4_parameters); |
| 7939 | sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align, | 8190 | sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align, |
| 7940 | mbx_sli4_parameters); | 8191 | mbx_sli4_parameters); |
| 8192 | phba->sli4_hba.extents_in_use = bf_get(cfg_ext, mbx_sli4_parameters); | ||
| 8193 | phba->sli4_hba.rpi_hdrs_in_use = bf_get(cfg_hdrr, mbx_sli4_parameters); | ||
| 8194 | |||
| 8195 | /* Make sure that sge_supp_len can be handled by the driver */ | ||
| 8196 | if (sli4_params->sge_supp_len > LPFC_MAX_SGE_SIZE) | ||
| 8197 | sli4_params->sge_supp_len = LPFC_MAX_SGE_SIZE; | ||
| 8198 | |||
| 7941 | return 0; | 8199 | return 0; |
| 7942 | } | 8200 | } |
| 7943 | 8201 | ||
| @@ -8173,6 +8431,10 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) | |||
| 8173 | 8431 | ||
| 8174 | lpfc_debugfs_terminate(vport); | 8432 | lpfc_debugfs_terminate(vport); |
| 8175 | 8433 | ||
| 8434 | /* Disable SR-IOV if enabled */ | ||
| 8435 | if (phba->cfg_sriov_nr_virtfn) | ||
| 8436 | pci_disable_sriov(pdev); | ||
| 8437 | |||
| 8176 | /* Disable interrupt */ | 8438 | /* Disable interrupt */ |
| 8177 | lpfc_sli_disable_intr(phba); | 8439 | lpfc_sli_disable_intr(phba); |
| 8178 | 8440 | ||
| @@ -8565,6 +8827,97 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba) | |||
| 8565 | } | 8827 | } |
| 8566 | 8828 | ||
| 8567 | /** | 8829 | /** |
| 8830 | * lpfc_write_firmware - attempt to write a firmware image to the port | ||
| 8831 | * @phba: pointer to lpfc hba data structure. | ||
| 8832 | * @fw: pointer to firmware image returned from request_firmware. | ||
| 8833 | * | ||
| 8834 | * returns the number of bytes written if write is successful. | ||
| 8835 | * returns a negative error value if there were errors. | ||
| 8836 | * returns 0 if firmware matches currently active firmware on port. | ||
| 8837 | **/ | ||
| 8838 | int | ||
| 8839 | lpfc_write_firmware(struct lpfc_hba *phba, const struct firmware *fw) | ||
| 8840 | { | ||
| 8841 | char fwrev[32]; | ||
| 8842 | struct lpfc_grp_hdr *image = (struct lpfc_grp_hdr *)fw->data; | ||
| 8843 | struct list_head dma_buffer_list; | ||
| 8844 | int i, rc = 0; | ||
| 8845 | struct lpfc_dmabuf *dmabuf, *next; | ||
| 8846 | uint32_t offset = 0, temp_offset = 0; | ||
| 8847 | |||
| 8848 | INIT_LIST_HEAD(&dma_buffer_list); | ||
| 8849 | if ((image->magic_number != LPFC_GROUP_OJECT_MAGIC_NUM) || | ||
| 8850 | (bf_get(lpfc_grp_hdr_file_type, image) != LPFC_FILE_TYPE_GROUP) || | ||
| 8851 | (bf_get(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) || | ||
| 8852 | (image->size != fw->size)) { | ||
| 8853 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8854 | "3022 Invalid FW image found. " | ||
| 8855 | "Magic:%d Type:%x ID:%x\n", | ||
| 8856 | image->magic_number, | ||
| 8857 | bf_get(lpfc_grp_hdr_file_type, image), | ||
| 8858 | bf_get(lpfc_grp_hdr_id, image)); | ||
| 8859 | return -EINVAL; | ||
| 8860 | } | ||
| 8861 | lpfc_decode_firmware_rev(phba, fwrev, 1); | ||
| 8862 | if (strncmp(fwrev, image->rev_name, strnlen(fwrev, 16))) { | ||
| 8863 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8864 | "3023 Updating Firmware. Current Version:%s " | ||
| 8865 | "New Version:%s\n", | ||
| 8866 | fwrev, image->rev_name); | ||
| 8867 | for (i = 0; i < LPFC_MBX_WR_CONFIG_MAX_BDE; i++) { | ||
| 8868 | dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), | ||
| 8869 | GFP_KERNEL); | ||
| 8870 | if (!dmabuf) { | ||
| 8871 | rc = -ENOMEM; | ||
| 8872 | goto out; | ||
| 8873 | } | ||
| 8874 | dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, | ||
| 8875 | SLI4_PAGE_SIZE, | ||
| 8876 | &dmabuf->phys, | ||
| 8877 | GFP_KERNEL); | ||
| 8878 | if (!dmabuf->virt) { | ||
| 8879 | kfree(dmabuf); | ||
| 8880 | rc = -ENOMEM; | ||
| 8881 | goto out; | ||
| 8882 | } | ||
| 8883 | list_add_tail(&dmabuf->list, &dma_buffer_list); | ||
| 8884 | } | ||
| 8885 | while (offset < fw->size) { | ||
| 8886 | temp_offset = offset; | ||
| 8887 | list_for_each_entry(dmabuf, &dma_buffer_list, list) { | ||
| 8888 | if (offset + SLI4_PAGE_SIZE > fw->size) { | ||
| 8889 | temp_offset += fw->size - offset; | ||
| 8890 | memcpy(dmabuf->virt, | ||
| 8891 | fw->data + temp_offset, | ||
| 8892 | fw->size - offset); | ||
| 8893 | break; | ||
| 8894 | } | ||
| 8895 | temp_offset += SLI4_PAGE_SIZE; | ||
| 8896 | memcpy(dmabuf->virt, fw->data + temp_offset, | ||
| 8897 | SLI4_PAGE_SIZE); | ||
| 8898 | } | ||
| 8899 | rc = lpfc_wr_object(phba, &dma_buffer_list, | ||
| 8900 | (fw->size - offset), &offset); | ||
| 8901 | if (rc) { | ||
| 8902 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8903 | "3024 Firmware update failed. " | ||
| 8904 | "%d\n", rc); | ||
| 8905 | goto out; | ||
| 8906 | } | ||
| 8907 | } | ||
| 8908 | rc = offset; | ||
| 8909 | } | ||
| 8910 | out: | ||
| 8911 | list_for_each_entry_safe(dmabuf, next, &dma_buffer_list, list) { | ||
| 8912 | list_del(&dmabuf->list); | ||
| 8913 | dma_free_coherent(&phba->pcidev->dev, SLI4_PAGE_SIZE, | ||
| 8914 | dmabuf->virt, dmabuf->phys); | ||
| 8915 | kfree(dmabuf); | ||
| 8916 | } | ||
| 8917 | return rc; | ||
| 8918 | } | ||
| 8919 | |||
| 8920 | /** | ||
| 8568 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys | 8921 | * lpfc_pci_probe_one_s4 - PCI probe func to reg SLI-4 device to PCI subsys |
| 8569 | * @pdev: pointer to PCI device | 8922 | * @pdev: pointer to PCI device |
| 8570 | * @pid: pointer to PCI device identifier | 8923 | * @pid: pointer to PCI device identifier |
| @@ -8591,6 +8944,10 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 8591 | int error; | 8944 | int error; |
| 8592 | uint32_t cfg_mode, intr_mode; | 8945 | uint32_t cfg_mode, intr_mode; |
| 8593 | int mcnt; | 8946 | int mcnt; |
| 8947 | int adjusted_fcp_eq_count; | ||
| 8948 | int fcp_qidx; | ||
| 8949 | const struct firmware *fw; | ||
| 8950 | uint8_t file_name[16]; | ||
| 8594 | 8951 | ||
| 8595 | /* Allocate memory for HBA structure */ | 8952 | /* Allocate memory for HBA structure */ |
| 8596 | phba = lpfc_hba_alloc(pdev); | 8953 | phba = lpfc_hba_alloc(pdev); |
| @@ -8688,11 +9045,25 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 8688 | error = -ENODEV; | 9045 | error = -ENODEV; |
| 8689 | goto out_free_sysfs_attr; | 9046 | goto out_free_sysfs_attr; |
| 8690 | } | 9047 | } |
| 8691 | /* Default to single FCP EQ for non-MSI-X */ | 9048 | /* Default to single EQ for non-MSI-X */ |
| 8692 | if (phba->intr_type != MSIX) | 9049 | if (phba->intr_type != MSIX) |
| 8693 | phba->cfg_fcp_eq_count = 1; | 9050 | adjusted_fcp_eq_count = 0; |
| 8694 | else if (phba->sli4_hba.msix_vec_nr < phba->cfg_fcp_eq_count) | 9051 | else if (phba->sli4_hba.msix_vec_nr < |
| 8695 | phba->cfg_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; | 9052 | phba->cfg_fcp_eq_count + 1) |
| 9053 | adjusted_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1; | ||
| 9054 | else | ||
| 9055 | adjusted_fcp_eq_count = phba->cfg_fcp_eq_count; | ||
| 9056 | /* Free unused EQs */ | ||
| 9057 | for (fcp_qidx = adjusted_fcp_eq_count; | ||
| 9058 | fcp_qidx < phba->cfg_fcp_eq_count; | ||
| 9059 | fcp_qidx++) { | ||
| 9060 | lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]); | ||
| 9061 | /* do not delete the first fcp_cq */ | ||
| 9062 | if (fcp_qidx) | ||
| 9063 | lpfc_sli4_queue_free( | ||
| 9064 | phba->sli4_hba.fcp_cq[fcp_qidx]); | ||
| 9065 | } | ||
| 9066 | phba->cfg_fcp_eq_count = adjusted_fcp_eq_count; | ||
| 8696 | /* Set up SLI-4 HBA */ | 9067 | /* Set up SLI-4 HBA */ |
| 8697 | if (lpfc_sli4_hba_setup(phba)) { | 9068 | if (lpfc_sli4_hba_setup(phba)) { |
| 8698 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 9069 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
| @@ -8731,6 +9102,14 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 8731 | /* Perform post initialization setup */ | 9102 | /* Perform post initialization setup */ |
| 8732 | lpfc_post_init_setup(phba); | 9103 | lpfc_post_init_setup(phba); |
| 8733 | 9104 | ||
| 9105 | /* check for firmware upgrade or downgrade */ | ||
| 9106 | snprintf(file_name, 16, "%s.grp", phba->ModelName); | ||
| 9107 | error = request_firmware(&fw, file_name, &phba->pcidev->dev); | ||
| 9108 | if (!error) { | ||
| 9109 | lpfc_write_firmware(phba, fw); | ||
| 9110 | release_firmware(fw); | ||
| 9111 | } | ||
| 9112 | |||
| 8734 | /* Check if there are static vports to be created. */ | 9113 | /* Check if there are static vports to be created. */ |
| 8735 | lpfc_create_static_vport(phba); | 9114 | lpfc_create_static_vport(phba); |
| 8736 | 9115 | ||
| @@ -9498,6 +9877,10 @@ static struct pci_device_id lpfc_id_table[] = { | |||
| 9498 | PCI_ANY_ID, PCI_ANY_ID, }, | 9877 | PCI_ANY_ID, PCI_ANY_ID, }, |
| 9499 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE, | 9878 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE, |
| 9500 | PCI_ANY_ID, PCI_ANY_ID, }, | 9879 | PCI_ANY_ID, PCI_ANY_ID, }, |
| 9880 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF, | ||
| 9881 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
| 9882 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF, | ||
| 9883 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
| 9501 | { 0 } | 9884 | { 0 } |
| 9502 | }; | 9885 | }; |
| 9503 | 9886 | ||
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e6ce9033f85e..556767028353 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -610,7 +610,8 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) | |||
| 610 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); | 610 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); |
| 611 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); | 611 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); |
| 612 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); | 612 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); |
| 613 | mb->un.varRdSparm.vpi = vpi + phba->vpi_base; | 613 | if (phba->sli_rev >= LPFC_SLI_REV3) |
| 614 | mb->un.varRdSparm.vpi = phba->vpi_ids[vpi]; | ||
| 614 | 615 | ||
| 615 | /* save address for completion */ | 616 | /* save address for completion */ |
| 616 | pmb->context1 = mp; | 617 | pmb->context1 = mp; |
| @@ -643,9 +644,10 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, | |||
| 643 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 644 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
| 644 | 645 | ||
| 645 | mb->un.varUnregDID.did = did; | 646 | mb->un.varUnregDID.did = did; |
| 646 | if (vpi != 0xffff) | ||
| 647 | vpi += phba->vpi_base; | ||
| 648 | mb->un.varUnregDID.vpi = vpi; | 647 | mb->un.varUnregDID.vpi = vpi; |
| 648 | if ((vpi != 0xffff) && | ||
| 649 | (phba->sli_rev == LPFC_SLI_REV4)) | ||
| 650 | mb->un.varUnregDID.vpi = phba->vpi_ids[vpi]; | ||
| 649 | 651 | ||
| 650 | mb->mbxCommand = MBX_UNREG_D_ID; | 652 | mb->mbxCommand = MBX_UNREG_D_ID; |
| 651 | mb->mbxOwner = OWN_HOST; | 653 | mb->mbxOwner = OWN_HOST; |
| @@ -738,12 +740,10 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
| 738 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 740 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
| 739 | 741 | ||
| 740 | mb->un.varRegLogin.rpi = 0; | 742 | mb->un.varRegLogin.rpi = 0; |
| 741 | if (phba->sli_rev == LPFC_SLI_REV4) { | 743 | if (phba->sli_rev == LPFC_SLI_REV4) |
| 742 | mb->un.varRegLogin.rpi = rpi; | 744 | mb->un.varRegLogin.rpi = phba->sli4_hba.rpi_ids[rpi]; |
| 743 | if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR) | 745 | if (phba->sli_rev >= LPFC_SLI_REV3) |
| 744 | return 1; | 746 | mb->un.varRegLogin.vpi = phba->vpi_ids[vpi]; |
| 745 | } | ||
| 746 | mb->un.varRegLogin.vpi = vpi + phba->vpi_base; | ||
| 747 | mb->un.varRegLogin.did = did; | 747 | mb->un.varRegLogin.did = did; |
| 748 | mb->mbxOwner = OWN_HOST; | 748 | mb->mbxOwner = OWN_HOST; |
| 749 | /* Get a buffer to hold NPorts Service Parameters */ | 749 | /* Get a buffer to hold NPorts Service Parameters */ |
| @@ -757,7 +757,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
| 757 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, | 757 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, |
| 758 | "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " | 758 | "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " |
| 759 | "rpi x%x\n", vpi, did, rpi); | 759 | "rpi x%x\n", vpi, did, rpi); |
| 760 | return (1); | 760 | return 1; |
| 761 | } | 761 | } |
| 762 | INIT_LIST_HEAD(&mp->list); | 762 | INIT_LIST_HEAD(&mp->list); |
| 763 | sparam = mp->virt; | 763 | sparam = mp->virt; |
| @@ -773,7 +773,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
| 773 | mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); | 773 | mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); |
| 774 | mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); | 774 | mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); |
| 775 | 775 | ||
| 776 | return (0); | 776 | return 0; |
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | /** | 779 | /** |
| @@ -789,6 +789,9 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | |||
| 789 | * | 789 | * |
| 790 | * This routine prepares the mailbox command for unregistering remote port | 790 | * This routine prepares the mailbox command for unregistering remote port |
| 791 | * login. | 791 | * login. |
| 792 | * | ||
| 793 | * For SLI4 ports, the rpi passed to this function must be the physical | ||
| 794 | * rpi value, not the logical index. | ||
| 792 | **/ | 795 | **/ |
| 793 | void | 796 | void |
| 794 | lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | 797 | lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, |
| @@ -799,9 +802,10 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | |||
| 799 | mb = &pmb->u.mb; | 802 | mb = &pmb->u.mb; |
| 800 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 803 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
| 801 | 804 | ||
| 802 | mb->un.varUnregLogin.rpi = (uint16_t) rpi; | 805 | mb->un.varUnregLogin.rpi = rpi; |
| 803 | mb->un.varUnregLogin.rsvd1 = 0; | 806 | mb->un.varUnregLogin.rsvd1 = 0; |
| 804 | mb->un.varUnregLogin.vpi = vpi + phba->vpi_base; | 807 | if (phba->sli_rev >= LPFC_SLI_REV3) |
| 808 | mb->un.varUnregLogin.vpi = phba->vpi_ids[vpi]; | ||
| 805 | 809 | ||
| 806 | mb->mbxCommand = MBX_UNREG_LOGIN; | 810 | mb->mbxCommand = MBX_UNREG_LOGIN; |
| 807 | mb->mbxOwner = OWN_HOST; | 811 | mb->mbxOwner = OWN_HOST; |
| @@ -825,9 +829,16 @@ lpfc_sli4_unreg_all_rpis(struct lpfc_vport *vport) | |||
| 825 | 829 | ||
| 826 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 830 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 827 | if (mbox) { | 831 | if (mbox) { |
| 828 | lpfc_unreg_login(phba, vport->vpi, | 832 | /* |
| 829 | vport->vpi + phba->vpi_base, mbox); | 833 | * For SLI4 functions, the rpi field is overloaded for |
| 830 | mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000 ; | 834 | * the vport context unreg all. This routine passes |
| 835 | * 0 for the rpi field in lpfc_unreg_login for compatibility | ||
| 836 | * with SLI3 and then overrides the rpi field with the | ||
| 837 | * expected value for SLI4. | ||
| 838 | */ | ||
| 839 | lpfc_unreg_login(phba, vport->vpi, phba->vpi_ids[vport->vpi], | ||
| 840 | mbox); | ||
| 841 | mbox->u.mb.un.varUnregLogin.rsvd1 = 0x4000; | ||
| 831 | mbox->vport = vport; | 842 | mbox->vport = vport; |
| 832 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 843 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 833 | mbox->context1 = NULL; | 844 | mbox->context1 = NULL; |
| @@ -865,9 +876,13 @@ lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) | |||
| 865 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 876 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
| 866 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) | 877 | !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) |
| 867 | mb->un.varRegVpi.upd = 1; | 878 | mb->un.varRegVpi.upd = 1; |
| 868 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; | 879 | |
| 880 | mb->un.varRegVpi.vpi = phba->vpi_ids[vport->vpi]; | ||
| 869 | mb->un.varRegVpi.sid = vport->fc_myDID; | 881 | mb->un.varRegVpi.sid = vport->fc_myDID; |
| 870 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | 882 | if (phba->sli_rev == LPFC_SLI_REV4) |
| 883 | mb->un.varRegVpi.vfi = phba->sli4_hba.vfi_ids[vport->vfi]; | ||
| 884 | else | ||
| 885 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | ||
| 871 | memcpy(mb->un.varRegVpi.wwn, &vport->fc_portname, | 886 | memcpy(mb->un.varRegVpi.wwn, &vport->fc_portname, |
| 872 | sizeof(struct lpfc_name)); | 887 | sizeof(struct lpfc_name)); |
| 873 | mb->un.varRegVpi.wwn[0] = cpu_to_le32(mb->un.varRegVpi.wwn[0]); | 888 | mb->un.varRegVpi.wwn[0] = cpu_to_le32(mb->un.varRegVpi.wwn[0]); |
| @@ -901,10 +916,10 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) | |||
| 901 | MAILBOX_t *mb = &pmb->u.mb; | 916 | MAILBOX_t *mb = &pmb->u.mb; |
| 902 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 917 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
| 903 | 918 | ||
| 904 | if (phba->sli_rev < LPFC_SLI_REV4) | 919 | if (phba->sli_rev == LPFC_SLI_REV3) |
| 905 | mb->un.varUnregVpi.vpi = vpi + phba->vpi_base; | 920 | mb->un.varUnregVpi.vpi = phba->vpi_ids[vpi]; |
| 906 | else | 921 | else if (phba->sli_rev >= LPFC_SLI_REV4) |
| 907 | mb->un.varUnregVpi.sli4_vpi = vpi + phba->vpi_base; | 922 | mb->un.varUnregVpi.sli4_vpi = phba->vpi_ids[vpi]; |
| 908 | 923 | ||
| 909 | mb->mbxCommand = MBX_UNREG_VPI; | 924 | mb->mbxCommand = MBX_UNREG_VPI; |
| 910 | mb->mbxOwner = OWN_HOST; | 925 | mb->mbxOwner = OWN_HOST; |
| @@ -1735,12 +1750,12 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
| 1735 | return length; | 1750 | return length; |
| 1736 | } | 1751 | } |
| 1737 | 1752 | ||
| 1738 | /* Setup for the none-embedded mbox command */ | 1753 | /* Setup for the non-embedded mbox command */ |
| 1739 | pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE; | 1754 | pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE; |
| 1740 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? | 1755 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? |
| 1741 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; | 1756 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; |
| 1742 | /* Allocate record for keeping SGE virtual addresses */ | 1757 | /* Allocate record for keeping SGE virtual addresses */ |
| 1743 | mbox->sge_array = kmalloc(sizeof(struct lpfc_mbx_nembed_sge_virt), | 1758 | mbox->sge_array = kzalloc(sizeof(struct lpfc_mbx_nembed_sge_virt), |
| 1744 | GFP_KERNEL); | 1759 | GFP_KERNEL); |
| 1745 | if (!mbox->sge_array) { | 1760 | if (!mbox->sge_array) { |
| 1746 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | 1761 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, |
| @@ -1790,12 +1805,87 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
| 1790 | /* The sub-header is in DMA memory, which needs endian converstion */ | 1805 | /* The sub-header is in DMA memory, which needs endian converstion */ |
| 1791 | if (cfg_shdr) | 1806 | if (cfg_shdr) |
| 1792 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, | 1807 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, |
| 1793 | sizeof(union lpfc_sli4_cfg_shdr)); | 1808 | sizeof(union lpfc_sli4_cfg_shdr)); |
| 1794 | |||
| 1795 | return alloc_len; | 1809 | return alloc_len; |
| 1796 | } | 1810 | } |
| 1797 | 1811 | ||
| 1798 | /** | 1812 | /** |
| 1813 | * lpfc_sli4_mbox_rsrc_extent - Initialize the opcode resource extent. | ||
| 1814 | * @phba: pointer to lpfc hba data structure. | ||
| 1815 | * @mbox: pointer to an allocated lpfc mbox resource. | ||
| 1816 | * @exts_count: the number of extents, if required, to allocate. | ||
| 1817 | * @rsrc_type: the resource extent type. | ||
| 1818 | * @emb: true if LPFC_SLI4_MBX_EMBED. false if LPFC_SLI4_MBX_NEMBED. | ||
| 1819 | * | ||
| 1820 | * This routine completes the subcommand header for SLI4 resource extent | ||
| 1821 | * mailbox commands. It is called after lpfc_sli4_config. The caller must | ||
| 1822 | * pass an allocated mailbox and the attributes required to initialize the | ||
| 1823 | * mailbox correctly. | ||
| 1824 | * | ||
| 1825 | * Return: the actual length of the mbox command allocated. | ||
| 1826 | **/ | ||
| 1827 | int | ||
| 1828 | lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | ||
| 1829 | uint16_t exts_count, uint16_t rsrc_type, bool emb) | ||
| 1830 | { | ||
| 1831 | uint8_t opcode = 0; | ||
| 1832 | struct lpfc_mbx_nembed_rsrc_extent *n_rsrc_extnt = NULL; | ||
| 1833 | void *virtaddr = NULL; | ||
| 1834 | |||
| 1835 | /* Set up SLI4 ioctl command header fields */ | ||
| 1836 | if (emb == LPFC_SLI4_MBX_NEMBED) { | ||
| 1837 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
| 1838 | virtaddr = mbox->sge_array->addr[0]; | ||
| 1839 | if (virtaddr == NULL) | ||
| 1840 | return 1; | ||
| 1841 | n_rsrc_extnt = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr; | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | /* | ||
| 1845 | * The resource type is common to all extent Opcodes and resides in the | ||
| 1846 | * same position. | ||
| 1847 | */ | ||
| 1848 | if (emb == LPFC_SLI4_MBX_EMBED) | ||
| 1849 | bf_set(lpfc_mbx_alloc_rsrc_extents_type, | ||
| 1850 | &mbox->u.mqe.un.alloc_rsrc_extents.u.req, | ||
| 1851 | rsrc_type); | ||
| 1852 | else { | ||
| 1853 | /* This is DMA data. Byteswap is required. */ | ||
| 1854 | bf_set(lpfc_mbx_alloc_rsrc_extents_type, | ||
| 1855 | n_rsrc_extnt, rsrc_type); | ||
| 1856 | lpfc_sli_pcimem_bcopy(&n_rsrc_extnt->word4, | ||
| 1857 | &n_rsrc_extnt->word4, | ||
| 1858 | sizeof(uint32_t)); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | /* Complete the initialization for the particular Opcode. */ | ||
| 1862 | opcode = lpfc_sli4_mbox_opcode_get(phba, mbox); | ||
| 1863 | switch (opcode) { | ||
| 1864 | case LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT: | ||
| 1865 | if (emb == LPFC_SLI4_MBX_EMBED) | ||
| 1866 | bf_set(lpfc_mbx_alloc_rsrc_extents_cnt, | ||
| 1867 | &mbox->u.mqe.un.alloc_rsrc_extents.u.req, | ||
| 1868 | exts_count); | ||
| 1869 | else | ||
| 1870 | bf_set(lpfc_mbx_alloc_rsrc_extents_cnt, | ||
| 1871 | n_rsrc_extnt, exts_count); | ||
| 1872 | break; | ||
| 1873 | case LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT: | ||
| 1874 | case LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO: | ||
| 1875 | case LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT: | ||
| 1876 | /* Initialization is complete.*/ | ||
| 1877 | break; | ||
| 1878 | default: | ||
| 1879 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | ||
| 1880 | "2929 Resource Extent Opcode x%x is " | ||
| 1881 | "unsupported\n", opcode); | ||
| 1882 | return 1; | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | return 0; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | /** | ||
| 1799 | * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command | 1889 | * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command |
| 1800 | * @phba: pointer to lpfc hba data structure. | 1890 | * @phba: pointer to lpfc hba data structure. |
| 1801 | * @mbox: pointer to lpfc mbox command. | 1891 | * @mbox: pointer to lpfc mbox command. |
| @@ -1939,9 +2029,12 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) | |||
| 1939 | bf_set(lpfc_init_vfi_vr, init_vfi, 1); | 2029 | bf_set(lpfc_init_vfi_vr, init_vfi, 1); |
| 1940 | bf_set(lpfc_init_vfi_vt, init_vfi, 1); | 2030 | bf_set(lpfc_init_vfi_vt, init_vfi, 1); |
| 1941 | bf_set(lpfc_init_vfi_vp, init_vfi, 1); | 2031 | bf_set(lpfc_init_vfi_vp, init_vfi, 1); |
| 1942 | bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base); | 2032 | bf_set(lpfc_init_vfi_vfi, init_vfi, |
| 1943 | bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base); | 2033 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); |
| 1944 | bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi); | 2034 | bf_set(lpfc_init_vpi_vpi, init_vfi, |
| 2035 | vport->phba->vpi_ids[vport->vpi]); | ||
| 2036 | bf_set(lpfc_init_vfi_fcfi, init_vfi, | ||
| 2037 | vport->phba->fcf.fcfi); | ||
| 1945 | } | 2038 | } |
| 1946 | 2039 | ||
| 1947 | /** | 2040 | /** |
| @@ -1964,9 +2057,10 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) | |||
| 1964 | reg_vfi = &mbox->u.mqe.un.reg_vfi; | 2057 | reg_vfi = &mbox->u.mqe.un.reg_vfi; |
| 1965 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI); | 2058 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI); |
| 1966 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 1); | 2059 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 1); |
| 1967 | bf_set(lpfc_reg_vfi_vfi, reg_vfi, vport->vfi + vport->phba->vfi_base); | 2060 | bf_set(lpfc_reg_vfi_vfi, reg_vfi, |
| 2061 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); | ||
| 1968 | bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi); | 2062 | bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi); |
| 1969 | bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->vpi + vport->phba->vpi_base); | 2063 | bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->phba->vpi_ids[vport->vpi]); |
| 1970 | memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name)); | 2064 | memcpy(reg_vfi->wwn, &vport->fc_portname, sizeof(struct lpfc_name)); |
| 1971 | reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]); | 2065 | reg_vfi->wwn[0] = cpu_to_le32(reg_vfi->wwn[0]); |
| 1972 | reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); | 2066 | reg_vfi->wwn[1] = cpu_to_le32(reg_vfi->wwn[1]); |
| @@ -1997,9 +2091,9 @@ lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi) | |||
| 1997 | memset(mbox, 0, sizeof(*mbox)); | 2091 | memset(mbox, 0, sizeof(*mbox)); |
| 1998 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); | 2092 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); |
| 1999 | bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, | 2093 | bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, |
| 2000 | vpi + phba->vpi_base); | 2094 | phba->vpi_ids[vpi]); |
| 2001 | bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi, | 2095 | bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi, |
| 2002 | phba->pport->vfi + phba->vfi_base); | 2096 | phba->sli4_hba.vfi_ids[phba->pport->vfi]); |
| 2003 | } | 2097 | } |
| 2004 | 2098 | ||
| 2005 | /** | 2099 | /** |
| @@ -2019,7 +2113,7 @@ lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) | |||
| 2019 | memset(mbox, 0, sizeof(*mbox)); | 2113 | memset(mbox, 0, sizeof(*mbox)); |
| 2020 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI); | 2114 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI); |
| 2021 | bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, | 2115 | bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, |
| 2022 | vport->vfi + vport->phba->vfi_base); | 2116 | vport->phba->sli4_hba.vfi_ids[vport->vfi]); |
| 2023 | } | 2117 | } |
| 2024 | 2118 | ||
| 2025 | /** | 2119 | /** |
| @@ -2131,12 +2225,14 @@ lpfc_unreg_fcfi(struct lpfcMboxq *mbox, uint16_t fcfi) | |||
| 2131 | void | 2225 | void |
| 2132 | lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp) | 2226 | lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp) |
| 2133 | { | 2227 | { |
| 2228 | struct lpfc_hba *phba = ndlp->phba; | ||
| 2134 | struct lpfc_mbx_resume_rpi *resume_rpi; | 2229 | struct lpfc_mbx_resume_rpi *resume_rpi; |
| 2135 | 2230 | ||
| 2136 | memset(mbox, 0, sizeof(*mbox)); | 2231 | memset(mbox, 0, sizeof(*mbox)); |
| 2137 | resume_rpi = &mbox->u.mqe.un.resume_rpi; | 2232 | resume_rpi = &mbox->u.mqe.un.resume_rpi; |
| 2138 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI); | 2233 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI); |
| 2139 | bf_set(lpfc_resume_rpi_index, resume_rpi, ndlp->nlp_rpi); | 2234 | bf_set(lpfc_resume_rpi_index, resume_rpi, |
| 2235 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
| 2140 | bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI); | 2236 | bf_set(lpfc_resume_rpi_ii, resume_rpi, RESUME_INDEX_RPI); |
| 2141 | resume_rpi->event_tag = ndlp->phba->fc_eventTag; | 2237 | resume_rpi->event_tag = ndlp->phba->fc_eventTag; |
| 2142 | } | 2238 | } |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index cbb48ee8b0bb..10d5b5e41499 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
| @@ -62,7 +62,6 @@ int | |||
| 62 | lpfc_mem_alloc(struct lpfc_hba *phba, int align) | 62 | lpfc_mem_alloc(struct lpfc_hba *phba, int align) |
| 63 | { | 63 | { |
| 64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | 64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; |
| 65 | int longs; | ||
| 66 | int i; | 65 | int i; |
| 67 | 66 | ||
| 68 | if (phba->sli_rev == LPFC_SLI_REV4) | 67 | if (phba->sli_rev == LPFC_SLI_REV4) |
| @@ -138,17 +137,8 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) | |||
| 138 | phba->lpfc_hrb_pool = NULL; | 137 | phba->lpfc_hrb_pool = NULL; |
| 139 | phba->lpfc_drb_pool = NULL; | 138 | phba->lpfc_drb_pool = NULL; |
| 140 | } | 139 | } |
| 141 | /* vpi zero is reserved for the physical port so add 1 to max */ | ||
| 142 | longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 143 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL); | ||
| 144 | if (!phba->vpi_bmask) | ||
| 145 | goto fail_free_dbq_pool; | ||
| 146 | 140 | ||
| 147 | return 0; | 141 | return 0; |
| 148 | |||
| 149 | fail_free_dbq_pool: | ||
| 150 | pci_pool_destroy(phba->lpfc_drb_pool); | ||
| 151 | phba->lpfc_drb_pool = NULL; | ||
| 152 | fail_free_hrb_pool: | 142 | fail_free_hrb_pool: |
| 153 | pci_pool_destroy(phba->lpfc_hrb_pool); | 143 | pci_pool_destroy(phba->lpfc_hrb_pool); |
| 154 | phba->lpfc_hrb_pool = NULL; | 144 | phba->lpfc_hrb_pool = NULL; |
| @@ -191,9 +181,6 @@ lpfc_mem_free(struct lpfc_hba *phba) | |||
| 191 | int i; | 181 | int i; |
| 192 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | 182 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; |
| 193 | 183 | ||
| 194 | /* Free VPI bitmask memory */ | ||
| 195 | kfree(phba->vpi_bmask); | ||
| 196 | |||
| 197 | /* Free HBQ pools */ | 184 | /* Free HBQ pools */ |
| 198 | lpfc_sli_hbqbuf_free_all(phba); | 185 | lpfc_sli_hbqbuf_free_all(phba); |
| 199 | if (phba->lpfc_drb_pool) | 186 | if (phba->lpfc_drb_pool) |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 0d92d4205ea6..2ddd02f7c603 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
| @@ -350,11 +350,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 350 | ndlp->nlp_maxframe = | 350 | ndlp->nlp_maxframe = |
| 351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; | 351 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
| 352 | 352 | ||
| 353 | /* | 353 | /* no need to reg_login if we are already in one of these states */ |
| 354 | * Need to unreg_login if we are already in one of these states and | ||
| 355 | * change to NPR state. This will block the port until after the ACC | ||
| 356 | * completes and the reg_login is issued and completed. | ||
| 357 | */ | ||
| 358 | switch (ndlp->nlp_state) { | 354 | switch (ndlp->nlp_state) { |
| 359 | case NLP_STE_NPR_NODE: | 355 | case NLP_STE_NPR_NODE: |
| 360 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) | 356 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) |
| @@ -363,9 +359,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 363 | case NLP_STE_PRLI_ISSUE: | 359 | case NLP_STE_PRLI_ISSUE: |
| 364 | case NLP_STE_UNMAPPED_NODE: | 360 | case NLP_STE_UNMAPPED_NODE: |
| 365 | case NLP_STE_MAPPED_NODE: | 361 | case NLP_STE_MAPPED_NODE: |
| 366 | lpfc_unreg_rpi(vport, ndlp); | 362 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); |
| 367 | ndlp->nlp_prev_state = ndlp->nlp_state; | 363 | return 1; |
| 368 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
| 369 | } | 364 | } |
| 370 | 365 | ||
| 371 | if ((vport->fc_flag & FC_PT2PT) && | 366 | if ((vport->fc_flag & FC_PT2PT) && |
| @@ -657,6 +652,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 657 | lpfc_unreg_rpi(vport, ndlp); | 652 | lpfc_unreg_rpi(vport, ndlp); |
| 658 | return 0; | 653 | return 0; |
| 659 | } | 654 | } |
| 655 | |||
| 660 | /** | 656 | /** |
| 661 | * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. | 657 | * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd. |
| 662 | * @phba : Pointer to lpfc_hba structure. | 658 | * @phba : Pointer to lpfc_hba structure. |
| @@ -1399,8 +1395,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
| 1399 | if (mb->mbxStatus) { | 1395 | if (mb->mbxStatus) { |
| 1400 | /* RegLogin failed */ | 1396 | /* RegLogin failed */ |
| 1401 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 1397 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
| 1402 | "0246 RegLogin failed Data: x%x x%x x%x\n", | 1398 | "0246 RegLogin failed Data: x%x x%x x%x x%x " |
| 1403 | did, mb->mbxStatus, vport->port_state); | 1399 | "x%x\n", |
| 1400 | did, mb->mbxStatus, vport->port_state, | ||
| 1401 | mb->un.varRegLogin.vpi, | ||
| 1402 | mb->un.varRegLogin.rpi); | ||
| 1404 | /* | 1403 | /* |
| 1405 | * If RegLogin failed due to lack of HBA resources do not | 1404 | * If RegLogin failed due to lack of HBA resources do not |
| 1406 | * retry discovery. | 1405 | * retry discovery. |
| @@ -1424,7 +1423,10 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
| 1424 | return ndlp->nlp_state; | 1423 | return ndlp->nlp_state; |
| 1425 | } | 1424 | } |
| 1426 | 1425 | ||
| 1427 | ndlp->nlp_rpi = mb->un.varWords[0]; | 1426 | /* SLI4 ports have preallocated logical rpis. */ |
| 1427 | if (vport->phba->sli_rev < LPFC_SLI_REV4) | ||
| 1428 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
| 1429 | |||
| 1428 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 1430 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
| 1429 | 1431 | ||
| 1430 | /* Only if we are not a fabric nport do we issue PRLI */ | 1432 | /* Only if we are not a fabric nport do we issue PRLI */ |
| @@ -2025,7 +2027,9 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport, | |||
| 2025 | MAILBOX_t *mb = &pmb->u.mb; | 2027 | MAILBOX_t *mb = &pmb->u.mb; |
| 2026 | 2028 | ||
| 2027 | if (!mb->mbxStatus) { | 2029 | if (!mb->mbxStatus) { |
| 2028 | ndlp->nlp_rpi = mb->un.varWords[0]; | 2030 | /* SLI4 ports have preallocated logical rpis. */ |
| 2031 | if (vport->phba->sli_rev < LPFC_SLI_REV4) | ||
| 2032 | ndlp->nlp_rpi = mb->un.varWords[0]; | ||
| 2029 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 2033 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
| 2030 | } else { | 2034 | } else { |
| 2031 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { | 2035 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 84e4481b2406..3ccc97496ebf 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -743,7 +743,14 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | |||
| 743 | if (bcnt == 0) | 743 | if (bcnt == 0) |
| 744 | continue; | 744 | continue; |
| 745 | /* Now, post the SCSI buffer list sgls as a block */ | 745 | /* Now, post the SCSI buffer list sgls as a block */ |
| 746 | status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt); | 746 | if (!phba->sli4_hba.extents_in_use) |
| 747 | status = lpfc_sli4_post_scsi_sgl_block(phba, | ||
| 748 | &sblist, | ||
| 749 | bcnt); | ||
| 750 | else | ||
| 751 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | ||
| 752 | &sblist, | ||
| 753 | bcnt); | ||
| 747 | /* Reset SCSI buffer count for next round of posting */ | 754 | /* Reset SCSI buffer count for next round of posting */ |
| 748 | bcnt = 0; | 755 | bcnt = 0; |
| 749 | while (!list_empty(&sblist)) { | 756 | while (!list_empty(&sblist)) { |
| @@ -787,7 +794,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 787 | dma_addr_t pdma_phys_fcp_cmd; | 794 | dma_addr_t pdma_phys_fcp_cmd; |
| 788 | dma_addr_t pdma_phys_fcp_rsp; | 795 | dma_addr_t pdma_phys_fcp_rsp; |
| 789 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; | 796 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; |
| 790 | uint16_t iotag, last_xritag = NO_XRI; | 797 | uint16_t iotag, last_xritag = NO_XRI, lxri = 0; |
| 791 | int status = 0, index; | 798 | int status = 0, index; |
| 792 | int bcnt; | 799 | int bcnt; |
| 793 | int non_sequential_xri = 0; | 800 | int non_sequential_xri = 0; |
| @@ -823,13 +830,15 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 823 | break; | 830 | break; |
| 824 | } | 831 | } |
| 825 | 832 | ||
| 826 | psb->cur_iocbq.sli4_xritag = lpfc_sli4_next_xritag(phba); | 833 | lxri = lpfc_sli4_next_xritag(phba); |
| 827 | if (psb->cur_iocbq.sli4_xritag == NO_XRI) { | 834 | if (lxri == NO_XRI) { |
| 828 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | 835 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, |
| 829 | psb->data, psb->dma_handle); | 836 | psb->data, psb->dma_handle); |
| 830 | kfree(psb); | 837 | kfree(psb); |
| 831 | break; | 838 | break; |
| 832 | } | 839 | } |
| 840 | psb->cur_iocbq.sli4_lxritag = lxri; | ||
| 841 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | ||
| 833 | if (last_xritag != NO_XRI | 842 | if (last_xritag != NO_XRI |
| 834 | && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) { | 843 | && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) { |
| 835 | non_sequential_xri = 1; | 844 | non_sequential_xri = 1; |
| @@ -861,6 +870,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 861 | */ | 870 | */ |
| 862 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); | 871 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd)); |
| 863 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); | 872 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd)); |
| 873 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
| 864 | bf_set(lpfc_sli4_sge_last, sgl, 0); | 874 | bf_set(lpfc_sli4_sge_last, sgl, 0); |
| 865 | sgl->word2 = cpu_to_le32(sgl->word2); | 875 | sgl->word2 = cpu_to_le32(sgl->word2); |
| 866 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd)); | 876 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd)); |
| @@ -869,6 +879,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 869 | /* Setup the physical region for the FCP RSP */ | 879 | /* Setup the physical region for the FCP RSP */ |
| 870 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp)); | 880 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp)); |
| 871 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp)); | 881 | sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp)); |
| 882 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
| 872 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 883 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
| 873 | sgl->word2 = cpu_to_le32(sgl->word2); | 884 | sgl->word2 = cpu_to_le32(sgl->word2); |
| 874 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp)); | 885 | sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp)); |
| @@ -914,7 +925,21 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 914 | } | 925 | } |
| 915 | } | 926 | } |
| 916 | if (bcnt) { | 927 | if (bcnt) { |
| 917 | status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt); | 928 | if (!phba->sli4_hba.extents_in_use) |
| 929 | status = lpfc_sli4_post_scsi_sgl_block(phba, | ||
| 930 | &sblist, | ||
| 931 | bcnt); | ||
| 932 | else | ||
| 933 | status = lpfc_sli4_post_scsi_sgl_blk_ext(phba, | ||
| 934 | &sblist, | ||
| 935 | bcnt); | ||
| 936 | |||
| 937 | if (status) { | ||
| 938 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
| 939 | "3021 SCSI SGL post error %d\n", | ||
| 940 | status); | ||
| 941 | bcnt = 0; | ||
| 942 | } | ||
| 918 | /* Reset SCSI buffer count for next round of posting */ | 943 | /* Reset SCSI buffer count for next round of posting */ |
| 919 | while (!list_empty(&sblist)) { | 944 | while (!list_empty(&sblist)) { |
| 920 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, | 945 | list_remove_head(&sblist, psb, struct lpfc_scsi_buf, |
| @@ -2081,6 +2106,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 2081 | dma_len = sg_dma_len(sgel); | 2106 | dma_len = sg_dma_len(sgel); |
| 2082 | sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); | 2107 | sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr)); |
| 2083 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); | 2108 | sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr)); |
| 2109 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
| 2084 | if ((num_bde + 1) == nseg) | 2110 | if ((num_bde + 1) == nseg) |
| 2085 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 2111 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
| 2086 | else | 2112 | else |
| @@ -2794,6 +2820,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2794 | * of the scsi_cmnd request_buffer | 2820 | * of the scsi_cmnd request_buffer |
| 2795 | */ | 2821 | */ |
| 2796 | piocbq->iocb.ulpContext = pnode->nlp_rpi; | 2822 | piocbq->iocb.ulpContext = pnode->nlp_rpi; |
| 2823 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 2824 | piocbq->iocb.ulpContext = | ||
| 2825 | phba->sli4_hba.rpi_ids[pnode->nlp_rpi]; | ||
| 2797 | if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) | 2826 | if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) |
| 2798 | piocbq->iocb.ulpFCP2Rcvy = 1; | 2827 | piocbq->iocb.ulpFCP2Rcvy = 1; |
| 2799 | else | 2828 | else |
| @@ -2807,7 +2836,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2807 | } | 2836 | } |
| 2808 | 2837 | ||
| 2809 | /** | 2838 | /** |
| 2810 | * lpfc_scsi_prep_task_mgmt_cmnd - Convert SLI3 scsi TM cmd to FCP info unit | 2839 | * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit |
| 2811 | * @vport: The virtual port for which this call is being executed. | 2840 | * @vport: The virtual port for which this call is being executed. |
| 2812 | * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. | 2841 | * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. |
| 2813 | * @lun: Logical unit number. | 2842 | * @lun: Logical unit number. |
| @@ -2851,6 +2880,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, | |||
| 2851 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); | 2880 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); |
| 2852 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; | 2881 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; |
| 2853 | piocb->ulpContext = ndlp->nlp_rpi; | 2882 | piocb->ulpContext = ndlp->nlp_rpi; |
| 2883 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { | ||
| 2884 | piocb->ulpContext = | ||
| 2885 | vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; | ||
| 2886 | } | ||
| 2854 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { | 2887 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
| 2855 | piocb->ulpFCP2Rcvy = 1; | 2888 | piocb->ulpFCP2Rcvy = 1; |
| 2856 | } | 2889 | } |
| @@ -3405,9 +3438,10 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
| 3405 | 3438 | ||
| 3406 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | 3439 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, |
| 3407 | "0702 Issue %s to TGT %d LUN %d " | 3440 | "0702 Issue %s to TGT %d LUN %d " |
| 3408 | "rpi x%x nlp_flag x%x\n", | 3441 | "rpi x%x nlp_flag x%x Data: x%x x%x\n", |
| 3409 | lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, | 3442 | lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, |
| 3410 | pnode->nlp_rpi, pnode->nlp_flag); | 3443 | pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, |
| 3444 | iocbq->iocb_flag); | ||
| 3411 | 3445 | ||
| 3412 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, | 3446 | status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, |
| 3413 | iocbq, iocbqrsp, lpfc_cmd->timeout); | 3447 | iocbq, iocbqrsp, lpfc_cmd->timeout); |
| @@ -3419,10 +3453,12 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, | |||
| 3419 | ret = FAILED; | 3453 | ret = FAILED; |
| 3420 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; | 3454 | lpfc_cmd->status = IOSTAT_DRIVER_REJECT; |
| 3421 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 3455 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
| 3422 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d)\n", | 3456 | "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " |
| 3457 | "iocb_flag x%x\n", | ||
| 3423 | lpfc_taskmgmt_name(task_mgmt_cmd), | 3458 | lpfc_taskmgmt_name(task_mgmt_cmd), |
| 3424 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, | 3459 | tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, |
| 3425 | iocbqrsp->iocb.un.ulpWord[4]); | 3460 | iocbqrsp->iocb.un.ulpWord[4], |
| 3461 | iocbq->iocb_flag); | ||
| 3426 | } else if (status == IOCB_BUSY) | 3462 | } else if (status == IOCB_BUSY) |
| 3427 | ret = FAILED; | 3463 | ret = FAILED; |
| 3428 | else | 3464 | else |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index fd5835e1c039..98999bbd8cbf 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -65,6 +65,9 @@ static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *, | |||
| 65 | struct lpfc_iocbq *); | 65 | struct lpfc_iocbq *); |
| 66 | static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, | 66 | static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, |
| 67 | struct hbq_dmabuf *); | 67 | struct hbq_dmabuf *); |
| 68 | static int lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *, struct lpfc_queue *, | ||
| 69 | struct lpfc_cqe *); | ||
| 70 | |||
| 68 | static IOCB_t * | 71 | static IOCB_t * |
| 69 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 72 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
| 70 | { | 73 | { |
| @@ -456,7 +459,6 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) | |||
| 456 | struct lpfc_iocbq * iocbq = NULL; | 459 | struct lpfc_iocbq * iocbq = NULL; |
| 457 | 460 | ||
| 458 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); | 461 | list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list); |
| 459 | |||
| 460 | if (iocbq) | 462 | if (iocbq) |
| 461 | phba->iocb_cnt++; | 463 | phba->iocb_cnt++; |
| 462 | if (phba->iocb_cnt > phba->iocb_max) | 464 | if (phba->iocb_cnt > phba->iocb_max) |
| @@ -479,13 +481,10 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) | |||
| 479 | static struct lpfc_sglq * | 481 | static struct lpfc_sglq * |
| 480 | __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | 482 | __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) |
| 481 | { | 483 | { |
| 482 | uint16_t adj_xri; | ||
| 483 | struct lpfc_sglq *sglq; | 484 | struct lpfc_sglq *sglq; |
| 484 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 485 | |
| 485 | if (adj_xri > phba->sli4_hba.max_cfg_param.max_xri) | 486 | sglq = phba->sli4_hba.lpfc_sglq_active_list[xritag]; |
| 486 | return NULL; | 487 | phba->sli4_hba.lpfc_sglq_active_list[xritag] = NULL; |
| 487 | sglq = phba->sli4_hba.lpfc_sglq_active_list[adj_xri]; | ||
| 488 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = NULL; | ||
| 489 | return sglq; | 488 | return sglq; |
| 490 | } | 489 | } |
| 491 | 490 | ||
| @@ -504,12 +503,9 @@ __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | |||
| 504 | struct lpfc_sglq * | 503 | struct lpfc_sglq * |
| 505 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) | 504 | __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) |
| 506 | { | 505 | { |
| 507 | uint16_t adj_xri; | ||
| 508 | struct lpfc_sglq *sglq; | 506 | struct lpfc_sglq *sglq; |
| 509 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 507 | |
| 510 | if (adj_xri > phba->sli4_hba.max_cfg_param.max_xri) | 508 | sglq = phba->sli4_hba.lpfc_sglq_active_list[xritag]; |
| 511 | return NULL; | ||
| 512 | sglq = phba->sli4_hba.lpfc_sglq_active_list[adj_xri]; | ||
| 513 | return sglq; | 509 | return sglq; |
| 514 | } | 510 | } |
| 515 | 511 | ||
| @@ -532,7 +528,6 @@ static int | |||
| 532 | __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 528 | __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, |
| 533 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) | 529 | uint16_t xritag, uint16_t rxid, uint16_t send_rrq) |
| 534 | { | 530 | { |
| 535 | uint16_t adj_xri; | ||
| 536 | struct lpfc_node_rrq *rrq; | 531 | struct lpfc_node_rrq *rrq; |
| 537 | int empty; | 532 | int empty; |
| 538 | uint32_t did = 0; | 533 | uint32_t did = 0; |
| @@ -553,21 +548,19 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
| 553 | /* | 548 | /* |
| 554 | * set the active bit even if there is no mem available. | 549 | * set the active bit even if there is no mem available. |
| 555 | */ | 550 | */ |
| 556 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
| 557 | |||
| 558 | if (NLP_CHK_FREE_REQ(ndlp)) | 551 | if (NLP_CHK_FREE_REQ(ndlp)) |
| 559 | goto out; | 552 | goto out; |
| 560 | 553 | ||
| 561 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) | 554 | if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) |
| 562 | goto out; | 555 | goto out; |
| 563 | 556 | ||
| 564 | if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | 557 | if (test_and_set_bit(xritag, ndlp->active_rrqs.xri_bitmap)) |
| 565 | goto out; | 558 | goto out; |
| 566 | 559 | ||
| 567 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); | 560 | rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); |
| 568 | if (rrq) { | 561 | if (rrq) { |
| 569 | rrq->send_rrq = send_rrq; | 562 | rrq->send_rrq = send_rrq; |
| 570 | rrq->xritag = xritag; | 563 | rrq->xritag = phba->sli4_hba.xri_ids[xritag]; |
| 571 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); | 564 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); |
| 572 | rrq->ndlp = ndlp; | 565 | rrq->ndlp = ndlp; |
| 573 | rrq->nlp_DID = ndlp->nlp_DID; | 566 | rrq->nlp_DID = ndlp->nlp_DID; |
| @@ -603,7 +596,6 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, | |||
| 603 | uint16_t xritag, | 596 | uint16_t xritag, |
| 604 | struct lpfc_node_rrq *rrq) | 597 | struct lpfc_node_rrq *rrq) |
| 605 | { | 598 | { |
| 606 | uint16_t adj_xri; | ||
| 607 | struct lpfc_nodelist *ndlp = NULL; | 599 | struct lpfc_nodelist *ndlp = NULL; |
| 608 | 600 | ||
| 609 | if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) | 601 | if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) |
| @@ -619,8 +611,7 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, | |||
| 619 | if (!ndlp) | 611 | if (!ndlp) |
| 620 | goto out; | 612 | goto out; |
| 621 | 613 | ||
| 622 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | 614 | if (test_and_clear_bit(xritag, ndlp->active_rrqs.xri_bitmap)) { |
| 623 | if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { | ||
| 624 | rrq->send_rrq = 0; | 615 | rrq->send_rrq = 0; |
| 625 | rrq->xritag = 0; | 616 | rrq->xritag = 0; |
| 626 | rrq->rrq_stop_time = 0; | 617 | rrq->rrq_stop_time = 0; |
| @@ -796,12 +787,9 @@ int | |||
| 796 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 787 | lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, |
| 797 | uint16_t xritag) | 788 | uint16_t xritag) |
| 798 | { | 789 | { |
| 799 | uint16_t adj_xri; | ||
| 800 | |||
| 801 | adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; | ||
| 802 | if (!ndlp) | 790 | if (!ndlp) |
| 803 | return 0; | 791 | return 0; |
| 804 | if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) | 792 | if (test_bit(xritag, ndlp->active_rrqs.xri_bitmap)) |
| 805 | return 1; | 793 | return 1; |
| 806 | else | 794 | else |
| 807 | return 0; | 795 | return 0; |
| @@ -841,7 +829,7 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
| 841 | * @piocb: Pointer to the iocbq. | 829 | * @piocb: Pointer to the iocbq. |
| 842 | * | 830 | * |
| 843 | * This function is called with hbalock held. This function | 831 | * This function is called with hbalock held. This function |
| 844 | * Gets a new driver sglq object from the sglq list. If the | 832 | * gets a new driver sglq object from the sglq list. If the |
| 845 | * list is not empty then it is successful, it returns pointer to the newly | 833 | * list is not empty then it is successful, it returns pointer to the newly |
| 846 | * allocated sglq object else it returns NULL. | 834 | * allocated sglq object else it returns NULL. |
| 847 | **/ | 835 | **/ |
| @@ -851,7 +839,6 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
| 851 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; | 839 | struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; |
| 852 | struct lpfc_sglq *sglq = NULL; | 840 | struct lpfc_sglq *sglq = NULL; |
| 853 | struct lpfc_sglq *start_sglq = NULL; | 841 | struct lpfc_sglq *start_sglq = NULL; |
| 854 | uint16_t adj_xri; | ||
| 855 | struct lpfc_scsi_buf *lpfc_cmd; | 842 | struct lpfc_scsi_buf *lpfc_cmd; |
| 856 | struct lpfc_nodelist *ndlp; | 843 | struct lpfc_nodelist *ndlp; |
| 857 | int found = 0; | 844 | int found = 0; |
| @@ -870,8 +857,6 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
| 870 | while (!found) { | 857 | while (!found) { |
| 871 | if (!sglq) | 858 | if (!sglq) |
| 872 | return NULL; | 859 | return NULL; |
| 873 | adj_xri = sglq->sli4_xritag - | ||
| 874 | phba->sli4_hba.max_cfg_param.xri_base; | ||
| 875 | if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { | 860 | if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { |
| 876 | /* This xri has an rrq outstanding for this DID. | 861 | /* This xri has an rrq outstanding for this DID. |
| 877 | * put it back in the list and get another xri. | 862 | * put it back in the list and get another xri. |
| @@ -888,7 +873,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
| 888 | } | 873 | } |
| 889 | sglq->ndlp = ndlp; | 874 | sglq->ndlp = ndlp; |
| 890 | found = 1; | 875 | found = 1; |
| 891 | phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; | 876 | phba->sli4_hba.lpfc_sglq_active_list[sglq->sli4_lxritag] = sglq; |
| 892 | sglq->state = SGL_ALLOCATED; | 877 | sglq->state = SGL_ALLOCATED; |
| 893 | } | 878 | } |
| 894 | return sglq; | 879 | return sglq; |
| @@ -944,7 +929,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
| 944 | if (iocbq->sli4_xritag == NO_XRI) | 929 | if (iocbq->sli4_xritag == NO_XRI) |
| 945 | sglq = NULL; | 930 | sglq = NULL; |
| 946 | else | 931 | else |
| 947 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_xritag); | 932 | sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_lxritag); |
| 933 | |||
| 948 | if (sglq) { | 934 | if (sglq) { |
| 949 | if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && | 935 | if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && |
| 950 | (sglq->state != SGL_XRI_ABORTED)) { | 936 | (sglq->state != SGL_XRI_ABORTED)) { |
| @@ -971,6 +957,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
| 971 | * Clean all volatile data fields, preserve iotag and node struct. | 957 | * Clean all volatile data fields, preserve iotag and node struct. |
| 972 | */ | 958 | */ |
| 973 | memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); | 959 | memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); |
| 960 | iocbq->sli4_lxritag = NO_XRI; | ||
| 974 | iocbq->sli4_xritag = NO_XRI; | 961 | iocbq->sli4_xritag = NO_XRI; |
| 975 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); | 962 | list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); |
| 976 | } | 963 | } |
| @@ -2113,7 +2100,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 2113 | pmb->u.mb.mbxCommand == MBX_REG_LOGIN64 && | 2100 | pmb->u.mb.mbxCommand == MBX_REG_LOGIN64 && |
| 2114 | !pmb->u.mb.mbxStatus) { | 2101 | !pmb->u.mb.mbxStatus) { |
| 2115 | rpi = pmb->u.mb.un.varWords[0]; | 2102 | rpi = pmb->u.mb.un.varWords[0]; |
| 2116 | vpi = pmb->u.mb.un.varRegLogin.vpi - phba->vpi_base; | 2103 | vpi = pmb->u.mb.un.varRegLogin.vpi; |
| 2117 | lpfc_unreg_login(phba, vpi, rpi, pmb); | 2104 | lpfc_unreg_login(phba, vpi, rpi, pmb); |
| 2118 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 2105 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| 2119 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 2106 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); |
| @@ -3881,8 +3868,10 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) | |||
| 3881 | list_del_init(&phba->sli4_hba.els_cq->list); | 3868 | list_del_init(&phba->sli4_hba.els_cq->list); |
| 3882 | for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++) | 3869 | for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++) |
| 3883 | list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list); | 3870 | list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list); |
| 3884 | for (qindx = 0; qindx < phba->cfg_fcp_eq_count; qindx++) | 3871 | qindx = 0; |
| 3872 | do | ||
| 3885 | list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list); | 3873 | list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list); |
| 3874 | while (++qindx < phba->cfg_fcp_eq_count); | ||
| 3886 | spin_unlock_irq(&phba->hbalock); | 3875 | spin_unlock_irq(&phba->hbalock); |
| 3887 | 3876 | ||
| 3888 | /* Now physically reset the device */ | 3877 | /* Now physically reset the device */ |
| @@ -4318,6 +4307,7 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) | |||
| 4318 | continue; | 4307 | continue; |
| 4319 | } else if (rc) | 4308 | } else if (rc) |
| 4320 | break; | 4309 | break; |
| 4310 | |||
| 4321 | phba->link_state = LPFC_INIT_MBX_CMDS; | 4311 | phba->link_state = LPFC_INIT_MBX_CMDS; |
| 4322 | lpfc_config_port(phba, pmb); | 4312 | lpfc_config_port(phba, pmb); |
| 4323 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 4313 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
| @@ -4421,7 +4411,8 @@ int | |||
| 4421 | lpfc_sli_hba_setup(struct lpfc_hba *phba) | 4411 | lpfc_sli_hba_setup(struct lpfc_hba *phba) |
| 4422 | { | 4412 | { |
| 4423 | uint32_t rc; | 4413 | uint32_t rc; |
| 4424 | int mode = 3; | 4414 | int mode = 3, i; |
| 4415 | int longs; | ||
| 4425 | 4416 | ||
| 4426 | switch (lpfc_sli_mode) { | 4417 | switch (lpfc_sli_mode) { |
| 4427 | case 2: | 4418 | case 2: |
| @@ -4491,6 +4482,35 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) | |||
| 4491 | if (rc) | 4482 | if (rc) |
| 4492 | goto lpfc_sli_hba_setup_error; | 4483 | goto lpfc_sli_hba_setup_error; |
| 4493 | 4484 | ||
| 4485 | /* Initialize VPIs. */ | ||
| 4486 | if (phba->sli_rev == LPFC_SLI_REV3) { | ||
| 4487 | /* | ||
| 4488 | * The VPI bitmask and physical ID array are allocated | ||
| 4489 | * and initialized once only - at driver load. A port | ||
| 4490 | * reset doesn't need to reinitialize this memory. | ||
| 4491 | */ | ||
| 4492 | if ((phba->vpi_bmask == NULL) && (phba->vpi_ids == NULL)) { | ||
| 4493 | longs = (phba->max_vpi + BITS_PER_LONG) / BITS_PER_LONG; | ||
| 4494 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), | ||
| 4495 | GFP_KERNEL); | ||
| 4496 | if (!phba->vpi_bmask) { | ||
| 4497 | rc = -ENOMEM; | ||
| 4498 | goto lpfc_sli_hba_setup_error; | ||
| 4499 | } | ||
| 4500 | |||
| 4501 | phba->vpi_ids = kzalloc( | ||
| 4502 | (phba->max_vpi+1) * sizeof(uint16_t), | ||
| 4503 | GFP_KERNEL); | ||
| 4504 | if (!phba->vpi_ids) { | ||
| 4505 | kfree(phba->vpi_bmask); | ||
| 4506 | rc = -ENOMEM; | ||
| 4507 | goto lpfc_sli_hba_setup_error; | ||
| 4508 | } | ||
| 4509 | for (i = 0; i < phba->max_vpi; i++) | ||
| 4510 | phba->vpi_ids[i] = i; | ||
| 4511 | } | ||
| 4512 | } | ||
| 4513 | |||
| 4494 | /* Init HBQs */ | 4514 | /* Init HBQs */ |
| 4495 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 4515 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
| 4496 | rc = lpfc_sli_hbq_setup(phba); | 4516 | rc = lpfc_sli_hbq_setup(phba); |
| @@ -4677,9 +4697,11 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | |||
| 4677 | 4697 | ||
| 4678 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); | 4698 | lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); |
| 4679 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); | 4699 | lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); |
| 4680 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) | 4700 | fcp_eqidx = 0; |
| 4701 | do | ||
| 4681 | lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], | 4702 | lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], |
| 4682 | LPFC_QUEUE_REARM); | 4703 | LPFC_QUEUE_REARM); |
| 4704 | while (++fcp_eqidx < phba->cfg_fcp_eq_count); | ||
| 4683 | lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM); | 4705 | lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM); |
| 4684 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) | 4706 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) |
| 4685 | lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], | 4707 | lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], |
| @@ -4687,6 +4709,803 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | |||
| 4687 | } | 4709 | } |
| 4688 | 4710 | ||
| 4689 | /** | 4711 | /** |
| 4712 | * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count. | ||
| 4713 | * @phba: Pointer to HBA context object. | ||
| 4714 | * @type: The resource extent type. | ||
| 4715 | * | ||
| 4716 | * This function allocates all SLI4 resource identifiers. | ||
| 4717 | **/ | ||
| 4718 | static int | ||
| 4719 | lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, | ||
| 4720 | uint16_t *extnt_count, uint16_t *extnt_size) | ||
| 4721 | { | ||
| 4722 | int rc = 0; | ||
| 4723 | uint32_t length; | ||
| 4724 | uint32_t mbox_tmo; | ||
| 4725 | struct lpfc_mbx_get_rsrc_extent_info *rsrc_info; | ||
| 4726 | LPFC_MBOXQ_t *mbox; | ||
| 4727 | |||
| 4728 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 4729 | if (!mbox) | ||
| 4730 | return -ENOMEM; | ||
| 4731 | |||
| 4732 | /* Find out how many extents are available for this resource type */ | ||
| 4733 | length = (sizeof(struct lpfc_mbx_get_rsrc_extent_info) - | ||
| 4734 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 4735 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 4736 | LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO, | ||
| 4737 | length, LPFC_SLI4_MBX_EMBED); | ||
| 4738 | |||
| 4739 | /* Send an extents count of 0 - the GET doesn't use it. */ | ||
| 4740 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, 0, type, | ||
| 4741 | LPFC_SLI4_MBX_EMBED); | ||
| 4742 | if (unlikely(rc)) { | ||
| 4743 | rc = -EIO; | ||
| 4744 | goto err_exit; | ||
| 4745 | } | ||
| 4746 | |||
| 4747 | if (!phba->sli4_hba.intr_enable) | ||
| 4748 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 4749 | else { | ||
| 4750 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 4751 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 4752 | } | ||
| 4753 | if (unlikely(rc)) { | ||
| 4754 | rc = -EIO; | ||
| 4755 | goto err_exit; | ||
| 4756 | } | ||
| 4757 | |||
| 4758 | rsrc_info = &mbox->u.mqe.un.rsrc_extent_info; | ||
| 4759 | if (bf_get(lpfc_mbox_hdr_status, | ||
| 4760 | &rsrc_info->header.cfg_shdr.response)) { | ||
| 4761 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
| 4762 | "2930 Failed to get resource extents " | ||
| 4763 | "Status 0x%x Add'l Status 0x%x\n", | ||
| 4764 | bf_get(lpfc_mbox_hdr_status, | ||
| 4765 | &rsrc_info->header.cfg_shdr.response), | ||
| 4766 | bf_get(lpfc_mbox_hdr_add_status, | ||
| 4767 | &rsrc_info->header.cfg_shdr.response)); | ||
| 4768 | rc = -EIO; | ||
| 4769 | goto err_exit; | ||
| 4770 | } | ||
| 4771 | |||
| 4772 | *extnt_count = bf_get(lpfc_mbx_get_rsrc_extent_info_cnt, | ||
| 4773 | &rsrc_info->u.rsp); | ||
| 4774 | *extnt_size = bf_get(lpfc_mbx_get_rsrc_extent_info_size, | ||
| 4775 | &rsrc_info->u.rsp); | ||
| 4776 | err_exit: | ||
| 4777 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 4778 | return rc; | ||
| 4779 | } | ||
| 4780 | |||
| 4781 | /** | ||
| 4782 | * lpfc_sli4_chk_avail_extnt_rsrc - Check for available SLI4 resource extents. | ||
| 4783 | * @phba: Pointer to HBA context object. | ||
| 4784 | * @type: The extent type to check. | ||
| 4785 | * | ||
| 4786 | * This function reads the current available extents from the port and checks | ||
| 4787 | * if the extent count or extent size has changed since the last access. | ||
| 4788 | * Callers use this routine post port reset to understand if there is a | ||
| 4789 | * extent reprovisioning requirement. | ||
| 4790 | * | ||
| 4791 | * Returns: | ||
| 4792 | * -Error: error indicates problem. | ||
| 4793 | * 1: Extent count or size has changed. | ||
| 4794 | * 0: No changes. | ||
| 4795 | **/ | ||
| 4796 | static int | ||
| 4797 | lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type) | ||
| 4798 | { | ||
| 4799 | uint16_t curr_ext_cnt, rsrc_ext_cnt; | ||
| 4800 | uint16_t size_diff, rsrc_ext_size; | ||
| 4801 | int rc = 0; | ||
| 4802 | struct lpfc_rsrc_blks *rsrc_entry; | ||
| 4803 | struct list_head *rsrc_blk_list = NULL; | ||
| 4804 | |||
| 4805 | size_diff = 0; | ||
| 4806 | curr_ext_cnt = 0; | ||
| 4807 | rc = lpfc_sli4_get_avail_extnt_rsrc(phba, type, | ||
| 4808 | &rsrc_ext_cnt, | ||
| 4809 | &rsrc_ext_size); | ||
| 4810 | if (unlikely(rc)) | ||
| 4811 | return -EIO; | ||
| 4812 | |||
| 4813 | switch (type) { | ||
| 4814 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
| 4815 | rsrc_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list; | ||
| 4816 | break; | ||
| 4817 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
| 4818 | rsrc_blk_list = &phba->lpfc_vpi_blk_list; | ||
| 4819 | break; | ||
| 4820 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
| 4821 | rsrc_blk_list = &phba->sli4_hba.lpfc_xri_blk_list; | ||
| 4822 | break; | ||
| 4823 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
| 4824 | rsrc_blk_list = &phba->sli4_hba.lpfc_vfi_blk_list; | ||
| 4825 | break; | ||
| 4826 | default: | ||
| 4827 | break; | ||
| 4828 | } | ||
| 4829 | |||
| 4830 | list_for_each_entry(rsrc_entry, rsrc_blk_list, list) { | ||
| 4831 | curr_ext_cnt++; | ||
| 4832 | if (rsrc_entry->rsrc_size != rsrc_ext_size) | ||
| 4833 | size_diff++; | ||
| 4834 | } | ||
| 4835 | |||
| 4836 | if (curr_ext_cnt != rsrc_ext_cnt || size_diff != 0) | ||
| 4837 | rc = 1; | ||
| 4838 | |||
| 4839 | return rc; | ||
| 4840 | } | ||
| 4841 | |||
| 4842 | /** | ||
| 4843 | * lpfc_sli4_cfg_post_extnts - | ||
| 4844 | * @phba: Pointer to HBA context object. | ||
| 4845 | * @extnt_cnt - number of available extents. | ||
| 4846 | * @type - the extent type (rpi, xri, vfi, vpi). | ||
| 4847 | * @emb - buffer to hold either MBX_EMBED or MBX_NEMBED operation. | ||
| 4848 | * @mbox - pointer to the caller's allocated mailbox structure. | ||
| 4849 | * | ||
| 4850 | * This function executes the extents allocation request. It also | ||
| 4851 | * takes care of the amount of memory needed to allocate or get the | ||
| 4852 | * allocated extents. It is the caller's responsibility to evaluate | ||
| 4853 | * the response. | ||
| 4854 | * | ||
| 4855 | * Returns: | ||
| 4856 | * -Error: Error value describes the condition found. | ||
| 4857 | * 0: if successful | ||
| 4858 | **/ | ||
| 4859 | static int | ||
| 4860 | lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt, | ||
| 4861 | uint16_t type, bool *emb, LPFC_MBOXQ_t *mbox) | ||
| 4862 | { | ||
| 4863 | int rc = 0; | ||
| 4864 | uint32_t req_len; | ||
| 4865 | uint32_t emb_len; | ||
| 4866 | uint32_t alloc_len, mbox_tmo; | ||
| 4867 | |||
| 4868 | /* Calculate the total requested length of the dma memory */ | ||
| 4869 | req_len = *extnt_cnt * sizeof(uint16_t); | ||
| 4870 | |||
| 4871 | /* | ||
| 4872 | * Calculate the size of an embedded mailbox. The uint32_t | ||
| 4873 | * accounts for extents-specific word. | ||
| 4874 | */ | ||
| 4875 | emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) - | ||
| 4876 | sizeof(uint32_t); | ||
| 4877 | |||
| 4878 | /* | ||
| 4879 | * Presume the allocation and response will fit into an embedded | ||
| 4880 | * mailbox. If not true, reconfigure to a non-embedded mailbox. | ||
| 4881 | */ | ||
| 4882 | *emb = LPFC_SLI4_MBX_EMBED; | ||
| 4883 | if (req_len > emb_len) { | ||
| 4884 | req_len = *extnt_cnt * sizeof(uint16_t) + | ||
| 4885 | sizeof(union lpfc_sli4_cfg_shdr) + | ||
| 4886 | sizeof(uint32_t); | ||
| 4887 | *emb = LPFC_SLI4_MBX_NEMBED; | ||
| 4888 | } | ||
| 4889 | |||
| 4890 | alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 4891 | LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT, | ||
| 4892 | req_len, *emb); | ||
| 4893 | if (alloc_len < req_len) { | ||
| 4894 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 4895 | "9000 Allocated DMA memory size (x%x) is " | ||
| 4896 | "less than the requested DMA memory " | ||
| 4897 | "size (x%x)\n", alloc_len, req_len); | ||
| 4898 | return -ENOMEM; | ||
| 4899 | } | ||
| 4900 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, *extnt_cnt, type, *emb); | ||
| 4901 | if (unlikely(rc)) | ||
| 4902 | return -EIO; | ||
| 4903 | |||
| 4904 | if (!phba->sli4_hba.intr_enable) | ||
| 4905 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 4906 | else { | ||
| 4907 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 4908 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 4909 | } | ||
| 4910 | |||
| 4911 | if (unlikely(rc)) | ||
| 4912 | rc = -EIO; | ||
| 4913 | return rc; | ||
| 4914 | } | ||
| 4915 | |||
| 4916 | /** | ||
| 4917 | * lpfc_sli4_alloc_extent - Allocate an SLI4 resource extent. | ||
| 4918 | * @phba: Pointer to HBA context object. | ||
| 4919 | * @type: The resource extent type to allocate. | ||
| 4920 | * | ||
| 4921 | * This function allocates the number of elements for the specified | ||
| 4922 | * resource type. | ||
| 4923 | **/ | ||
| 4924 | static int | ||
| 4925 | lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) | ||
| 4926 | { | ||
| 4927 | bool emb = false; | ||
| 4928 | uint16_t rsrc_id_cnt, rsrc_cnt, rsrc_size; | ||
| 4929 | uint16_t rsrc_id, rsrc_start, j, k; | ||
| 4930 | uint16_t *ids; | ||
| 4931 | int i, rc; | ||
| 4932 | unsigned long longs; | ||
| 4933 | unsigned long *bmask; | ||
| 4934 | struct lpfc_rsrc_blks *rsrc_blks; | ||
| 4935 | LPFC_MBOXQ_t *mbox; | ||
| 4936 | uint32_t length; | ||
| 4937 | struct lpfc_id_range *id_array = NULL; | ||
| 4938 | void *virtaddr = NULL; | ||
| 4939 | struct lpfc_mbx_nembed_rsrc_extent *n_rsrc; | ||
| 4940 | struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext; | ||
| 4941 | struct list_head *ext_blk_list; | ||
| 4942 | |||
| 4943 | rc = lpfc_sli4_get_avail_extnt_rsrc(phba, type, | ||
| 4944 | &rsrc_cnt, | ||
| 4945 | &rsrc_size); | ||
| 4946 | if (unlikely(rc)) | ||
| 4947 | return -EIO; | ||
| 4948 | |||
| 4949 | if ((rsrc_cnt == 0) || (rsrc_size == 0)) { | ||
| 4950 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
| 4951 | "3009 No available Resource Extents " | ||
| 4952 | "for resource type 0x%x: Count: 0x%x, " | ||
| 4953 | "Size 0x%x\n", type, rsrc_cnt, | ||
| 4954 | rsrc_size); | ||
| 4955 | return -ENOMEM; | ||
| 4956 | } | ||
| 4957 | |||
| 4958 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT, | ||
| 4959 | "2903 Available Resource Extents " | ||
| 4960 | "for resource type 0x%x: Count: 0x%x, " | ||
| 4961 | "Size 0x%x\n", type, rsrc_cnt, | ||
| 4962 | rsrc_size); | ||
| 4963 | |||
| 4964 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 4965 | if (!mbox) | ||
| 4966 | return -ENOMEM; | ||
| 4967 | |||
| 4968 | rc = lpfc_sli4_cfg_post_extnts(phba, &rsrc_cnt, type, &emb, mbox); | ||
| 4969 | if (unlikely(rc)) { | ||
| 4970 | rc = -EIO; | ||
| 4971 | goto err_exit; | ||
| 4972 | } | ||
| 4973 | |||
| 4974 | /* | ||
| 4975 | * Figure out where the response is located. Then get local pointers | ||
| 4976 | * to the response data. The port does not guarantee to respond to | ||
| 4977 | * all extents counts request so update the local variable with the | ||
| 4978 | * allocated count from the port. | ||
| 4979 | */ | ||
| 4980 | if (emb == LPFC_SLI4_MBX_EMBED) { | ||
| 4981 | rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents; | ||
| 4982 | id_array = &rsrc_ext->u.rsp.id[0]; | ||
| 4983 | rsrc_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp); | ||
| 4984 | } else { | ||
| 4985 | virtaddr = mbox->sge_array->addr[0]; | ||
| 4986 | n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr; | ||
| 4987 | rsrc_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc); | ||
| 4988 | id_array = &n_rsrc->id; | ||
| 4989 | } | ||
| 4990 | |||
| 4991 | longs = ((rsrc_cnt * rsrc_size) + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 4992 | rsrc_id_cnt = rsrc_cnt * rsrc_size; | ||
| 4993 | |||
| 4994 | /* | ||
| 4995 | * Based on the resource size and count, correct the base and max | ||
| 4996 | * resource values. | ||
| 4997 | */ | ||
| 4998 | length = sizeof(struct lpfc_rsrc_blks); | ||
| 4999 | switch (type) { | ||
| 5000 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
| 5001 | phba->sli4_hba.rpi_bmask = kzalloc(longs * | ||
| 5002 | sizeof(unsigned long), | ||
| 5003 | GFP_KERNEL); | ||
| 5004 | if (unlikely(!phba->sli4_hba.rpi_bmask)) { | ||
| 5005 | rc = -ENOMEM; | ||
| 5006 | goto err_exit; | ||
| 5007 | } | ||
| 5008 | phba->sli4_hba.rpi_ids = kzalloc(rsrc_id_cnt * | ||
| 5009 | sizeof(uint16_t), | ||
| 5010 | GFP_KERNEL); | ||
| 5011 | if (unlikely(!phba->sli4_hba.rpi_ids)) { | ||
| 5012 | kfree(phba->sli4_hba.rpi_bmask); | ||
| 5013 | rc = -ENOMEM; | ||
| 5014 | goto err_exit; | ||
| 5015 | } | ||
| 5016 | |||
| 5017 | /* | ||
| 5018 | * The next_rpi was initialized with the maximum available | ||
| 5019 | * count but the port may allocate a smaller number. Catch | ||
| 5020 | * that case and update the next_rpi. | ||
| 5021 | */ | ||
| 5022 | phba->sli4_hba.next_rpi = rsrc_id_cnt; | ||
| 5023 | |||
| 5024 | /* Initialize local ptrs for common extent processing later. */ | ||
| 5025 | bmask = phba->sli4_hba.rpi_bmask; | ||
| 5026 | ids = phba->sli4_hba.rpi_ids; | ||
| 5027 | ext_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list; | ||
| 5028 | break; | ||
| 5029 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
| 5030 | phba->vpi_bmask = kzalloc(longs * | ||
| 5031 | sizeof(unsigned long), | ||
| 5032 | GFP_KERNEL); | ||
| 5033 | if (unlikely(!phba->vpi_bmask)) { | ||
| 5034 | rc = -ENOMEM; | ||
| 5035 | goto err_exit; | ||
| 5036 | } | ||
| 5037 | phba->vpi_ids = kzalloc(rsrc_id_cnt * | ||
| 5038 | sizeof(uint16_t), | ||
| 5039 | GFP_KERNEL); | ||
| 5040 | if (unlikely(!phba->vpi_ids)) { | ||
| 5041 | kfree(phba->vpi_bmask); | ||
| 5042 | rc = -ENOMEM; | ||
| 5043 | goto err_exit; | ||
| 5044 | } | ||
| 5045 | |||
| 5046 | /* Initialize local ptrs for common extent processing later. */ | ||
| 5047 | bmask = phba->vpi_bmask; | ||
| 5048 | ids = phba->vpi_ids; | ||
| 5049 | ext_blk_list = &phba->lpfc_vpi_blk_list; | ||
| 5050 | break; | ||
| 5051 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
| 5052 | phba->sli4_hba.xri_bmask = kzalloc(longs * | ||
| 5053 | sizeof(unsigned long), | ||
| 5054 | GFP_KERNEL); | ||
| 5055 | if (unlikely(!phba->sli4_hba.xri_bmask)) { | ||
| 5056 | rc = -ENOMEM; | ||
| 5057 | goto err_exit; | ||
| 5058 | } | ||
| 5059 | phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt * | ||
| 5060 | sizeof(uint16_t), | ||
| 5061 | GFP_KERNEL); | ||
| 5062 | if (unlikely(!phba->sli4_hba.xri_ids)) { | ||
| 5063 | kfree(phba->sli4_hba.xri_bmask); | ||
| 5064 | rc = -ENOMEM; | ||
| 5065 | goto err_exit; | ||
| 5066 | } | ||
| 5067 | |||
| 5068 | /* Initialize local ptrs for common extent processing later. */ | ||
| 5069 | bmask = phba->sli4_hba.xri_bmask; | ||
| 5070 | ids = phba->sli4_hba.xri_ids; | ||
| 5071 | ext_blk_list = &phba->sli4_hba.lpfc_xri_blk_list; | ||
| 5072 | break; | ||
| 5073 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
| 5074 | phba->sli4_hba.vfi_bmask = kzalloc(longs * | ||
| 5075 | sizeof(unsigned long), | ||
| 5076 | GFP_KERNEL); | ||
| 5077 | if (unlikely(!phba->sli4_hba.vfi_bmask)) { | ||
| 5078 | rc = -ENOMEM; | ||
| 5079 | goto err_exit; | ||
| 5080 | } | ||
| 5081 | phba->sli4_hba.vfi_ids = kzalloc(rsrc_id_cnt * | ||
| 5082 | sizeof(uint16_t), | ||
| 5083 | GFP_KERNEL); | ||
| 5084 | if (unlikely(!phba->sli4_hba.vfi_ids)) { | ||
| 5085 | kfree(phba->sli4_hba.vfi_bmask); | ||
| 5086 | rc = -ENOMEM; | ||
| 5087 | goto err_exit; | ||
| 5088 | } | ||
| 5089 | |||
| 5090 | /* Initialize local ptrs for common extent processing later. */ | ||
| 5091 | bmask = phba->sli4_hba.vfi_bmask; | ||
| 5092 | ids = phba->sli4_hba.vfi_ids; | ||
| 5093 | ext_blk_list = &phba->sli4_hba.lpfc_vfi_blk_list; | ||
| 5094 | break; | ||
| 5095 | default: | ||
| 5096 | /* Unsupported Opcode. Fail call. */ | ||
| 5097 | id_array = NULL; | ||
| 5098 | bmask = NULL; | ||
| 5099 | ids = NULL; | ||
| 5100 | ext_blk_list = NULL; | ||
| 5101 | goto err_exit; | ||
| 5102 | } | ||
| 5103 | |||
| 5104 | /* | ||
| 5105 | * Complete initializing the extent configuration with the | ||
| 5106 | * allocated ids assigned to this function. The bitmask serves | ||
| 5107 | * as an index into the array and manages the available ids. The | ||
| 5108 | * array just stores the ids communicated to the port via the wqes. | ||
| 5109 | */ | ||
| 5110 | for (i = 0, j = 0, k = 0; i < rsrc_cnt; i++) { | ||
| 5111 | if ((i % 2) == 0) | ||
| 5112 | rsrc_id = bf_get(lpfc_mbx_rsrc_id_word4_0, | ||
| 5113 | &id_array[k]); | ||
| 5114 | else | ||
| 5115 | rsrc_id = bf_get(lpfc_mbx_rsrc_id_word4_1, | ||
| 5116 | &id_array[k]); | ||
| 5117 | |||
| 5118 | rsrc_blks = kzalloc(length, GFP_KERNEL); | ||
| 5119 | if (unlikely(!rsrc_blks)) { | ||
| 5120 | rc = -ENOMEM; | ||
| 5121 | kfree(bmask); | ||
| 5122 | kfree(ids); | ||
| 5123 | goto err_exit; | ||
| 5124 | } | ||
| 5125 | rsrc_blks->rsrc_start = rsrc_id; | ||
| 5126 | rsrc_blks->rsrc_size = rsrc_size; | ||
| 5127 | list_add_tail(&rsrc_blks->list, ext_blk_list); | ||
| 5128 | rsrc_start = rsrc_id; | ||
| 5129 | if ((type == LPFC_RSC_TYPE_FCOE_XRI) && (j == 0)) | ||
| 5130 | phba->sli4_hba.scsi_xri_start = rsrc_start + | ||
| 5131 | lpfc_sli4_get_els_iocb_cnt(phba); | ||
| 5132 | |||
| 5133 | while (rsrc_id < (rsrc_start + rsrc_size)) { | ||
| 5134 | ids[j] = rsrc_id; | ||
| 5135 | rsrc_id++; | ||
| 5136 | j++; | ||
| 5137 | } | ||
| 5138 | /* Entire word processed. Get next word.*/ | ||
| 5139 | if ((i % 2) == 1) | ||
| 5140 | k++; | ||
| 5141 | } | ||
| 5142 | err_exit: | ||
| 5143 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 5144 | return rc; | ||
| 5145 | } | ||
| 5146 | |||
| 5147 | /** | ||
| 5148 | * lpfc_sli4_dealloc_extent - Deallocate an SLI4 resource extent. | ||
| 5149 | * @phba: Pointer to HBA context object. | ||
| 5150 | * @type: the extent's type. | ||
| 5151 | * | ||
| 5152 | * This function deallocates all extents of a particular resource type. | ||
| 5153 | * SLI4 does not allow for deallocating a particular extent range. It | ||
| 5154 | * is the caller's responsibility to release all kernel memory resources. | ||
| 5155 | **/ | ||
| 5156 | static int | ||
| 5157 | lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) | ||
| 5158 | { | ||
| 5159 | int rc; | ||
| 5160 | uint32_t length, mbox_tmo = 0; | ||
| 5161 | LPFC_MBOXQ_t *mbox; | ||
| 5162 | struct lpfc_mbx_dealloc_rsrc_extents *dealloc_rsrc; | ||
| 5163 | struct lpfc_rsrc_blks *rsrc_blk, *rsrc_blk_next; | ||
| 5164 | |||
| 5165 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 5166 | if (!mbox) | ||
| 5167 | return -ENOMEM; | ||
| 5168 | |||
| 5169 | /* | ||
| 5170 | * This function sends an embedded mailbox because it only sends the | ||
| 5171 | * the resource type. All extents of this type are released by the | ||
| 5172 | * port. | ||
| 5173 | */ | ||
| 5174 | length = (sizeof(struct lpfc_mbx_dealloc_rsrc_extents) - | ||
| 5175 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
| 5176 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 5177 | LPFC_MBOX_OPCODE_DEALLOC_RSRC_EXTENT, | ||
| 5178 | length, LPFC_SLI4_MBX_EMBED); | ||
| 5179 | |||
| 5180 | /* Send an extents count of 0 - the dealloc doesn't use it. */ | ||
| 5181 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, 0, type, | ||
| 5182 | LPFC_SLI4_MBX_EMBED); | ||
| 5183 | if (unlikely(rc)) { | ||
| 5184 | rc = -EIO; | ||
| 5185 | goto out_free_mbox; | ||
| 5186 | } | ||
| 5187 | if (!phba->sli4_hba.intr_enable) | ||
| 5188 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 5189 | else { | ||
| 5190 | mbox_tmo = lpfc_mbox_tmo_val(phba, mbox_tmo); | ||
| 5191 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 5192 | } | ||
| 5193 | if (unlikely(rc)) { | ||
| 5194 | rc = -EIO; | ||
| 5195 | goto out_free_mbox; | ||
| 5196 | } | ||
| 5197 | |||
| 5198 | dealloc_rsrc = &mbox->u.mqe.un.dealloc_rsrc_extents; | ||
| 5199 | if (bf_get(lpfc_mbox_hdr_status, | ||
| 5200 | &dealloc_rsrc->header.cfg_shdr.response)) { | ||
| 5201 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
| 5202 | "2919 Failed to release resource extents " | ||
| 5203 | "for type %d - Status 0x%x Add'l Status 0x%x. " | ||
| 5204 | "Resource memory not released.\n", | ||
| 5205 | type, | ||
| 5206 | bf_get(lpfc_mbox_hdr_status, | ||
| 5207 | &dealloc_rsrc->header.cfg_shdr.response), | ||
| 5208 | bf_get(lpfc_mbox_hdr_add_status, | ||
| 5209 | &dealloc_rsrc->header.cfg_shdr.response)); | ||
| 5210 | rc = -EIO; | ||
| 5211 | goto out_free_mbox; | ||
| 5212 | } | ||
| 5213 | |||
| 5214 | /* Release kernel memory resources for the specific type. */ | ||
| 5215 | switch (type) { | ||
| 5216 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
| 5217 | kfree(phba->vpi_bmask); | ||
| 5218 | kfree(phba->vpi_ids); | ||
| 5219 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5220 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
| 5221 | &phba->lpfc_vpi_blk_list, list) { | ||
| 5222 | list_del_init(&rsrc_blk->list); | ||
| 5223 | kfree(rsrc_blk); | ||
| 5224 | } | ||
| 5225 | break; | ||
| 5226 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
| 5227 | kfree(phba->sli4_hba.xri_bmask); | ||
| 5228 | kfree(phba->sli4_hba.xri_ids); | ||
| 5229 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5230 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
| 5231 | &phba->sli4_hba.lpfc_xri_blk_list, list) { | ||
| 5232 | list_del_init(&rsrc_blk->list); | ||
| 5233 | kfree(rsrc_blk); | ||
| 5234 | } | ||
| 5235 | break; | ||
| 5236 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
| 5237 | kfree(phba->sli4_hba.vfi_bmask); | ||
| 5238 | kfree(phba->sli4_hba.vfi_ids); | ||
| 5239 | bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5240 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
| 5241 | &phba->sli4_hba.lpfc_vfi_blk_list, list) { | ||
| 5242 | list_del_init(&rsrc_blk->list); | ||
| 5243 | kfree(rsrc_blk); | ||
| 5244 | } | ||
| 5245 | break; | ||
| 5246 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
| 5247 | /* RPI bitmask and physical id array are cleaned up earlier. */ | ||
| 5248 | list_for_each_entry_safe(rsrc_blk, rsrc_blk_next, | ||
| 5249 | &phba->sli4_hba.lpfc_rpi_blk_list, list) { | ||
| 5250 | list_del_init(&rsrc_blk->list); | ||
| 5251 | kfree(rsrc_blk); | ||
| 5252 | } | ||
| 5253 | break; | ||
| 5254 | default: | ||
| 5255 | break; | ||
| 5256 | } | ||
| 5257 | |||
| 5258 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5259 | |||
| 5260 | out_free_mbox: | ||
| 5261 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 5262 | return rc; | ||
| 5263 | } | ||
| 5264 | |||
| 5265 | /** | ||
| 5266 | * lpfc_sli4_alloc_resource_identifiers - Allocate all SLI4 resource extents. | ||
| 5267 | * @phba: Pointer to HBA context object. | ||
| 5268 | * | ||
| 5269 | * This function allocates all SLI4 resource identifiers. | ||
| 5270 | **/ | ||
| 5271 | int | ||
| 5272 | lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) | ||
| 5273 | { | ||
| 5274 | int i, rc, error = 0; | ||
| 5275 | uint16_t count, base; | ||
| 5276 | unsigned long longs; | ||
| 5277 | |||
| 5278 | if (phba->sli4_hba.extents_in_use) { | ||
| 5279 | /* | ||
| 5280 | * The port supports resource extents. The XRI, VPI, VFI, RPI | ||
| 5281 | * resource extent count must be read and allocated before | ||
| 5282 | * provisioning the resource id arrays. | ||
| 5283 | */ | ||
| 5284 | if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) == | ||
| 5285 | LPFC_IDX_RSRC_RDY) { | ||
| 5286 | /* | ||
| 5287 | * Extent-based resources are set - the driver could | ||
| 5288 | * be in a port reset. Figure out if any corrective | ||
| 5289 | * actions need to be taken. | ||
| 5290 | */ | ||
| 5291 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
| 5292 | LPFC_RSC_TYPE_FCOE_VFI); | ||
| 5293 | if (rc != 0) | ||
| 5294 | error++; | ||
| 5295 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
| 5296 | LPFC_RSC_TYPE_FCOE_VPI); | ||
| 5297 | if (rc != 0) | ||
| 5298 | error++; | ||
| 5299 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
| 5300 | LPFC_RSC_TYPE_FCOE_XRI); | ||
| 5301 | if (rc != 0) | ||
| 5302 | error++; | ||
| 5303 | rc = lpfc_sli4_chk_avail_extnt_rsrc(phba, | ||
| 5304 | LPFC_RSC_TYPE_FCOE_RPI); | ||
| 5305 | if (rc != 0) | ||
| 5306 | error++; | ||
| 5307 | |||
| 5308 | /* | ||
| 5309 | * It's possible that the number of resources | ||
| 5310 | * provided to this port instance changed between | ||
| 5311 | * resets. Detect this condition and reallocate | ||
| 5312 | * resources. Otherwise, there is no action. | ||
| 5313 | */ | ||
| 5314 | if (error) { | ||
| 5315 | lpfc_printf_log(phba, KERN_INFO, | ||
| 5316 | LOG_MBOX | LOG_INIT, | ||
| 5317 | "2931 Detected extent resource " | ||
| 5318 | "change. Reallocating all " | ||
| 5319 | "extents.\n"); | ||
| 5320 | rc = lpfc_sli4_dealloc_extent(phba, | ||
| 5321 | LPFC_RSC_TYPE_FCOE_VFI); | ||
| 5322 | rc = lpfc_sli4_dealloc_extent(phba, | ||
| 5323 | LPFC_RSC_TYPE_FCOE_VPI); | ||
| 5324 | rc = lpfc_sli4_dealloc_extent(phba, | ||
| 5325 | LPFC_RSC_TYPE_FCOE_XRI); | ||
| 5326 | rc = lpfc_sli4_dealloc_extent(phba, | ||
| 5327 | LPFC_RSC_TYPE_FCOE_RPI); | ||
| 5328 | } else | ||
| 5329 | return 0; | ||
| 5330 | } | ||
| 5331 | |||
| 5332 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | ||
| 5333 | if (unlikely(rc)) | ||
| 5334 | goto err_exit; | ||
| 5335 | |||
| 5336 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_VPI); | ||
| 5337 | if (unlikely(rc)) | ||
| 5338 | goto err_exit; | ||
| 5339 | |||
| 5340 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_RPI); | ||
| 5341 | if (unlikely(rc)) | ||
| 5342 | goto err_exit; | ||
| 5343 | |||
| 5344 | rc = lpfc_sli4_alloc_extent(phba, LPFC_RSC_TYPE_FCOE_XRI); | ||
| 5345 | if (unlikely(rc)) | ||
| 5346 | goto err_exit; | ||
| 5347 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
| 5348 | LPFC_IDX_RSRC_RDY); | ||
| 5349 | return rc; | ||
| 5350 | } else { | ||
| 5351 | /* | ||
| 5352 | * The port does not support resource extents. The XRI, VPI, | ||
| 5353 | * VFI, RPI resource ids were determined from READ_CONFIG. | ||
| 5354 | * Just allocate the bitmasks and provision the resource id | ||
| 5355 | * arrays. If a port reset is active, the resources don't | ||
| 5356 | * need any action - just exit. | ||
| 5357 | */ | ||
| 5358 | if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) == | ||
| 5359 | LPFC_IDX_RSRC_RDY) | ||
| 5360 | return 0; | ||
| 5361 | |||
| 5362 | /* RPIs. */ | ||
| 5363 | count = phba->sli4_hba.max_cfg_param.max_rpi; | ||
| 5364 | base = phba->sli4_hba.max_cfg_param.rpi_base; | ||
| 5365 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 5366 | phba->sli4_hba.rpi_bmask = kzalloc(longs * | ||
| 5367 | sizeof(unsigned long), | ||
| 5368 | GFP_KERNEL); | ||
| 5369 | if (unlikely(!phba->sli4_hba.rpi_bmask)) { | ||
| 5370 | rc = -ENOMEM; | ||
| 5371 | goto err_exit; | ||
| 5372 | } | ||
| 5373 | phba->sli4_hba.rpi_ids = kzalloc(count * | ||
| 5374 | sizeof(uint16_t), | ||
| 5375 | GFP_KERNEL); | ||
| 5376 | if (unlikely(!phba->sli4_hba.rpi_ids)) { | ||
| 5377 | rc = -ENOMEM; | ||
| 5378 | goto free_rpi_bmask; | ||
| 5379 | } | ||
| 5380 | |||
| 5381 | for (i = 0; i < count; i++) | ||
| 5382 | phba->sli4_hba.rpi_ids[i] = base + i; | ||
| 5383 | |||
| 5384 | /* VPIs. */ | ||
| 5385 | count = phba->sli4_hba.max_cfg_param.max_vpi; | ||
| 5386 | base = phba->sli4_hba.max_cfg_param.vpi_base; | ||
| 5387 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 5388 | phba->vpi_bmask = kzalloc(longs * | ||
| 5389 | sizeof(unsigned long), | ||
| 5390 | GFP_KERNEL); | ||
| 5391 | if (unlikely(!phba->vpi_bmask)) { | ||
| 5392 | rc = -ENOMEM; | ||
| 5393 | goto free_rpi_ids; | ||
| 5394 | } | ||
| 5395 | phba->vpi_ids = kzalloc(count * | ||
| 5396 | sizeof(uint16_t), | ||
| 5397 | GFP_KERNEL); | ||
| 5398 | if (unlikely(!phba->vpi_ids)) { | ||
| 5399 | rc = -ENOMEM; | ||
| 5400 | goto free_vpi_bmask; | ||
| 5401 | } | ||
| 5402 | |||
| 5403 | for (i = 0; i < count; i++) | ||
| 5404 | phba->vpi_ids[i] = base + i; | ||
| 5405 | |||
| 5406 | /* XRIs. */ | ||
| 5407 | count = phba->sli4_hba.max_cfg_param.max_xri; | ||
| 5408 | base = phba->sli4_hba.max_cfg_param.xri_base; | ||
| 5409 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 5410 | phba->sli4_hba.xri_bmask = kzalloc(longs * | ||
| 5411 | sizeof(unsigned long), | ||
| 5412 | GFP_KERNEL); | ||
| 5413 | if (unlikely(!phba->sli4_hba.xri_bmask)) { | ||
| 5414 | rc = -ENOMEM; | ||
| 5415 | goto free_vpi_ids; | ||
| 5416 | } | ||
| 5417 | phba->sli4_hba.xri_ids = kzalloc(count * | ||
| 5418 | sizeof(uint16_t), | ||
| 5419 | GFP_KERNEL); | ||
| 5420 | if (unlikely(!phba->sli4_hba.xri_ids)) { | ||
| 5421 | rc = -ENOMEM; | ||
| 5422 | goto free_xri_bmask; | ||
| 5423 | } | ||
| 5424 | |||
| 5425 | for (i = 0; i < count; i++) | ||
| 5426 | phba->sli4_hba.xri_ids[i] = base + i; | ||
| 5427 | |||
| 5428 | /* VFIs. */ | ||
| 5429 | count = phba->sli4_hba.max_cfg_param.max_vfi; | ||
| 5430 | base = phba->sli4_hba.max_cfg_param.vfi_base; | ||
| 5431 | longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 5432 | phba->sli4_hba.vfi_bmask = kzalloc(longs * | ||
| 5433 | sizeof(unsigned long), | ||
| 5434 | GFP_KERNEL); | ||
| 5435 | if (unlikely(!phba->sli4_hba.vfi_bmask)) { | ||
| 5436 | rc = -ENOMEM; | ||
| 5437 | goto free_xri_ids; | ||
| 5438 | } | ||
| 5439 | phba->sli4_hba.vfi_ids = kzalloc(count * | ||
| 5440 | sizeof(uint16_t), | ||
| 5441 | GFP_KERNEL); | ||
| 5442 | if (unlikely(!phba->sli4_hba.vfi_ids)) { | ||
| 5443 | rc = -ENOMEM; | ||
| 5444 | goto free_vfi_bmask; | ||
| 5445 | } | ||
| 5446 | |||
| 5447 | for (i = 0; i < count; i++) | ||
| 5448 | phba->sli4_hba.vfi_ids[i] = base + i; | ||
| 5449 | |||
| 5450 | /* | ||
| 5451 | * Mark all resources ready. An HBA reset doesn't need | ||
| 5452 | * to reset the initialization. | ||
| 5453 | */ | ||
| 5454 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
| 5455 | LPFC_IDX_RSRC_RDY); | ||
| 5456 | return 0; | ||
| 5457 | } | ||
| 5458 | |||
| 5459 | free_vfi_bmask: | ||
| 5460 | kfree(phba->sli4_hba.vfi_bmask); | ||
| 5461 | free_xri_ids: | ||
| 5462 | kfree(phba->sli4_hba.xri_ids); | ||
| 5463 | free_xri_bmask: | ||
| 5464 | kfree(phba->sli4_hba.xri_bmask); | ||
| 5465 | free_vpi_ids: | ||
| 5466 | kfree(phba->vpi_ids); | ||
| 5467 | free_vpi_bmask: | ||
| 5468 | kfree(phba->vpi_bmask); | ||
| 5469 | free_rpi_ids: | ||
| 5470 | kfree(phba->sli4_hba.rpi_ids); | ||
| 5471 | free_rpi_bmask: | ||
| 5472 | kfree(phba->sli4_hba.rpi_bmask); | ||
| 5473 | err_exit: | ||
| 5474 | return rc; | ||
| 5475 | } | ||
| 5476 | |||
| 5477 | /** | ||
| 5478 | * lpfc_sli4_dealloc_resource_identifiers - Deallocate all SLI4 resource extents. | ||
| 5479 | * @phba: Pointer to HBA context object. | ||
| 5480 | * | ||
| 5481 | * This function allocates the number of elements for the specified | ||
| 5482 | * resource type. | ||
| 5483 | **/ | ||
| 5484 | int | ||
| 5485 | lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) | ||
| 5486 | { | ||
| 5487 | if (phba->sli4_hba.extents_in_use) { | ||
| 5488 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VPI); | ||
| 5489 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_RPI); | ||
| 5490 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_XRI); | ||
| 5491 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | ||
| 5492 | } else { | ||
| 5493 | kfree(phba->vpi_bmask); | ||
| 5494 | kfree(phba->vpi_ids); | ||
| 5495 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5496 | kfree(phba->sli4_hba.xri_bmask); | ||
| 5497 | kfree(phba->sli4_hba.xri_ids); | ||
| 5498 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5499 | kfree(phba->sli4_hba.vfi_bmask); | ||
| 5500 | kfree(phba->sli4_hba.vfi_ids); | ||
| 5501 | bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5502 | bf_set(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 5503 | } | ||
| 5504 | |||
| 5505 | return 0; | ||
| 5506 | } | ||
| 5507 | |||
| 5508 | /** | ||
| 4690 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function | 5509 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function |
| 4691 | * @phba: Pointer to HBA context object. | 5510 | * @phba: Pointer to HBA context object. |
| 4692 | * | 5511 | * |
| @@ -4708,10 +5527,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 4708 | struct lpfc_vport *vport = phba->pport; | 5527 | struct lpfc_vport *vport = phba->pport; |
| 4709 | struct lpfc_dmabuf *mp; | 5528 | struct lpfc_dmabuf *mp; |
| 4710 | 5529 | ||
| 4711 | /* | ||
| 4712 | * TODO: Why does this routine execute these task in a different | ||
| 4713 | * order from probe? | ||
| 4714 | */ | ||
| 4715 | /* Perform a PCI function reset to start from clean */ | 5530 | /* Perform a PCI function reset to start from clean */ |
| 4716 | rc = lpfc_pci_function_reset(phba); | 5531 | rc = lpfc_pci_function_reset(phba); |
| 4717 | if (unlikely(rc)) | 5532 | if (unlikely(rc)) |
| @@ -4740,7 +5555,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 4740 | * to read FCoE param config regions | 5555 | * to read FCoE param config regions |
| 4741 | */ | 5556 | */ |
| 4742 | if (lpfc_sli4_read_fcoe_params(phba, mboxq)) | 5557 | if (lpfc_sli4_read_fcoe_params(phba, mboxq)) |
| 4743 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | 5558 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT, |
| 4744 | "2570 Failed to read FCoE parameters\n"); | 5559 | "2570 Failed to read FCoE parameters\n"); |
| 4745 | 5560 | ||
| 4746 | /* Issue READ_REV to collect vpd and FW information. */ | 5561 | /* Issue READ_REV to collect vpd and FW information. */ |
| @@ -4873,6 +5688,18 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 4873 | phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED); | 5688 | phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED); |
| 4874 | spin_unlock_irq(&phba->hbalock); | 5689 | spin_unlock_irq(&phba->hbalock); |
| 4875 | 5690 | ||
| 5691 | /* | ||
| 5692 | * Allocate all resources (xri,rpi,vpi,vfi) now. Subsequent | ||
| 5693 | * calls depends on these resources to complete port setup. | ||
| 5694 | */ | ||
| 5695 | rc = lpfc_sli4_alloc_resource_identifiers(phba); | ||
| 5696 | if (rc) { | ||
| 5697 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
| 5698 | "2920 Failed to alloc Resource IDs " | ||
| 5699 | "rc = x%x\n", rc); | ||
| 5700 | goto out_free_mbox; | ||
| 5701 | } | ||
| 5702 | |||
| 4876 | /* Read the port's service parameters. */ | 5703 | /* Read the port's service parameters. */ |
| 4877 | rc = lpfc_read_sparam(phba, mboxq, vport->vpi); | 5704 | rc = lpfc_read_sparam(phba, mboxq, vport->vpi); |
| 4878 | if (rc) { | 5705 | if (rc) { |
| @@ -4906,35 +5733,37 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 4906 | goto out_free_mbox; | 5733 | goto out_free_mbox; |
| 4907 | } | 5734 | } |
| 4908 | 5735 | ||
| 4909 | if (phba->cfg_soft_wwnn) | 5736 | lpfc_update_vport_wwn(vport); |
| 4910 | u64_to_wwn(phba->cfg_soft_wwnn, | ||
| 4911 | vport->fc_sparam.nodeName.u.wwn); | ||
| 4912 | if (phba->cfg_soft_wwpn) | ||
| 4913 | u64_to_wwn(phba->cfg_soft_wwpn, | ||
| 4914 | vport->fc_sparam.portName.u.wwn); | ||
| 4915 | memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName, | ||
| 4916 | sizeof(struct lpfc_name)); | ||
| 4917 | memcpy(&vport->fc_portname, &vport->fc_sparam.portName, | ||
| 4918 | sizeof(struct lpfc_name)); | ||
| 4919 | 5737 | ||
| 4920 | /* Update the fc_host data structures with new wwn. */ | 5738 | /* Update the fc_host data structures with new wwn. */ |
| 4921 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); | 5739 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); |
| 4922 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); | 5740 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); |
| 4923 | 5741 | ||
| 4924 | /* Register SGL pool to the device using non-embedded mailbox command */ | 5742 | /* Register SGL pool to the device using non-embedded mailbox command */ |
| 4925 | rc = lpfc_sli4_post_sgl_list(phba); | 5743 | if (!phba->sli4_hba.extents_in_use) { |
| 4926 | if (unlikely(rc)) { | 5744 | rc = lpfc_sli4_post_els_sgl_list(phba); |
| 4927 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 5745 | if (unlikely(rc)) { |
| 4928 | "0582 Error %d during sgl post operation\n", | 5746 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
| 4929 | rc); | 5747 | "0582 Error %d during els sgl post " |
| 4930 | rc = -ENODEV; | 5748 | "operation\n", rc); |
| 4931 | goto out_free_mbox; | 5749 | rc = -ENODEV; |
| 5750 | goto out_free_mbox; | ||
| 5751 | } | ||
| 5752 | } else { | ||
| 5753 | rc = lpfc_sli4_post_els_sgl_list_ext(phba); | ||
| 5754 | if (unlikely(rc)) { | ||
| 5755 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | ||
| 5756 | "2560 Error %d during els sgl post " | ||
| 5757 | "operation\n", rc); | ||
| 5758 | rc = -ENODEV; | ||
| 5759 | goto out_free_mbox; | ||
| 5760 | } | ||
| 4932 | } | 5761 | } |
| 4933 | 5762 | ||
| 4934 | /* Register SCSI SGL pool to the device */ | 5763 | /* Register SCSI SGL pool to the device */ |
| 4935 | rc = lpfc_sli4_repost_scsi_sgl_list(phba); | 5764 | rc = lpfc_sli4_repost_scsi_sgl_list(phba); |
| 4936 | if (unlikely(rc)) { | 5765 | if (unlikely(rc)) { |
| 4937 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, | 5766 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
| 4938 | "0383 Error %d during scsi sgl post " | 5767 | "0383 Error %d during scsi sgl post " |
| 4939 | "operation\n", rc); | 5768 | "operation\n", rc); |
| 4940 | /* Some Scsi buffers were moved to the abort scsi list */ | 5769 | /* Some Scsi buffers were moved to the abort scsi list */ |
| @@ -5747,10 +6576,15 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 5747 | lpfc_sli_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe, | 6576 | lpfc_sli_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe, |
| 5748 | sizeof(struct lpfc_mcqe)); | 6577 | sizeof(struct lpfc_mcqe)); |
| 5749 | mcqe_status = bf_get(lpfc_mcqe_status, &mbox_rgn->mcqe); | 6578 | mcqe_status = bf_get(lpfc_mcqe_status, &mbox_rgn->mcqe); |
| 5750 | 6579 | /* | |
| 5751 | /* Prefix the mailbox status with range x4000 to note SLI4 status. */ | 6580 | * When the CQE status indicates a failure and the mailbox status |
| 6581 | * indicates success then copy the CQE status into the mailbox status | ||
| 6582 | * (and prefix it with x4000). | ||
| 6583 | */ | ||
| 5752 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { | 6584 | if (mcqe_status != MB_CQE_STATUS_SUCCESS) { |
| 5753 | bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status); | 6585 | if (bf_get(lpfc_mqe_status, mb) == MBX_SUCCESS) |
| 6586 | bf_set(lpfc_mqe_status, mb, | ||
| 6587 | (LPFC_MBX_ERROR_RANGE | mcqe_status)); | ||
| 5754 | rc = MBXERR_ERROR; | 6588 | rc = MBXERR_ERROR; |
| 5755 | } else | 6589 | } else |
| 5756 | lpfc_sli4_swap_str(phba, mboxq); | 6590 | lpfc_sli4_swap_str(phba, mboxq); |
| @@ -5819,7 +6653,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, | |||
| 5819 | else | 6653 | else |
| 5820 | rc = -EIO; | 6654 | rc = -EIO; |
| 5821 | if (rc != MBX_SUCCESS) | 6655 | if (rc != MBX_SUCCESS) |
| 5822 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 6656 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, |
| 5823 | "(%d):2541 Mailbox command x%x " | 6657 | "(%d):2541 Mailbox command x%x " |
| 5824 | "(x%x) cannot issue Data: x%x x%x\n", | 6658 | "(x%x) cannot issue Data: x%x x%x\n", |
| 5825 | mboxq->vport ? mboxq->vport->vpi : 0, | 6659 | mboxq->vport ? mboxq->vport->vpi : 0, |
| @@ -6307,6 +7141,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
| 6307 | sgl->addr_hi = bpl->addrHigh; | 7141 | sgl->addr_hi = bpl->addrHigh; |
| 6308 | sgl->addr_lo = bpl->addrLow; | 7142 | sgl->addr_lo = bpl->addrLow; |
| 6309 | 7143 | ||
| 7144 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
| 6310 | if ((i+1) == numBdes) | 7145 | if ((i+1) == numBdes) |
| 6311 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 7146 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
| 6312 | else | 7147 | else |
| @@ -6343,6 +7178,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
| 6343 | cpu_to_le32(icmd->un.genreq64.bdl.addrHigh); | 7178 | cpu_to_le32(icmd->un.genreq64.bdl.addrHigh); |
| 6344 | sgl->addr_lo = | 7179 | sgl->addr_lo = |
| 6345 | cpu_to_le32(icmd->un.genreq64.bdl.addrLow); | 7180 | cpu_to_le32(icmd->un.genreq64.bdl.addrLow); |
| 7181 | sgl->word2 = le32_to_cpu(sgl->word2); | ||
| 6346 | bf_set(lpfc_sli4_sge_last, sgl, 1); | 7182 | bf_set(lpfc_sli4_sge_last, sgl, 1); |
| 6347 | sgl->word2 = cpu_to_le32(sgl->word2); | 7183 | sgl->word2 = cpu_to_le32(sgl->word2); |
| 6348 | sgl->sge_len = | 7184 | sgl->sge_len = |
| @@ -6474,7 +7310,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
| 6474 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) | 7310 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) |
| 6475 | >> LPFC_FIP_ELS_ID_SHIFT); | 7311 | >> LPFC_FIP_ELS_ID_SHIFT); |
| 6476 | } | 7312 | } |
| 6477 | bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, ndlp->nlp_rpi); | 7313 | bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, |
| 7314 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
| 6478 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); | 7315 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); |
| 6479 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); | 7316 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); |
| 6480 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); | 7317 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); |
| @@ -6623,14 +7460,15 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
| 6623 | iocbq->iocb.ulpContext); | 7460 | iocbq->iocb.ulpContext); |
| 6624 | if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) | 7461 | if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) |
| 6625 | bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, | 7462 | bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, |
| 6626 | iocbq->vport->vpi + phba->vpi_base); | 7463 | phba->vpi_ids[iocbq->vport->vpi]); |
| 6627 | bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); | 7464 | bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); |
| 6628 | bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); | 7465 | bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); |
| 6629 | bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); | 7466 | bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); |
| 6630 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, | 7467 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, |
| 6631 | LPFC_WQE_LENLOC_WORD3); | 7468 | LPFC_WQE_LENLOC_WORD3); |
| 6632 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); | 7469 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); |
| 6633 | bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, ndlp->nlp_rpi); | 7470 | bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, |
| 7471 | phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); | ||
| 6634 | command_type = OTHER_COMMAND; | 7472 | command_type = OTHER_COMMAND; |
| 6635 | break; | 7473 | break; |
| 6636 | case CMD_CLOSE_XRI_CN: | 7474 | case CMD_CLOSE_XRI_CN: |
| @@ -6729,6 +7567,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
| 6729 | return IOCB_ERROR; | 7567 | return IOCB_ERROR; |
| 6730 | break; | 7568 | break; |
| 6731 | } | 7569 | } |
| 7570 | |||
| 6732 | bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); | 7571 | bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); |
| 6733 | bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); | 7572 | bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); |
| 6734 | wqe->generic.wqe_com.abort_tag = abort_tag; | 7573 | wqe->generic.wqe_com.abort_tag = abort_tag; |
| @@ -6776,7 +7615,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
| 6776 | return IOCB_BUSY; | 7615 | return IOCB_BUSY; |
| 6777 | } | 7616 | } |
| 6778 | } else { | 7617 | } else { |
| 6779 | sglq = __lpfc_sli_get_sglq(phba, piocb); | 7618 | sglq = __lpfc_sli_get_sglq(phba, piocb); |
| 6780 | if (!sglq) { | 7619 | if (!sglq) { |
| 6781 | if (!(flag & SLI_IOCB_RET_IOCB)) { | 7620 | if (!(flag & SLI_IOCB_RET_IOCB)) { |
| 6782 | __lpfc_sli_ringtx_put(phba, | 7621 | __lpfc_sli_ringtx_put(phba, |
| @@ -6789,11 +7628,11 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
| 6789 | } | 7628 | } |
| 6790 | } | 7629 | } |
| 6791 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { | 7630 | } else if (piocb->iocb_flag & LPFC_IO_FCP) { |
| 6792 | sglq = NULL; /* These IO's already have an XRI and | 7631 | /* These IO's already have an XRI and a mapped sgl. */ |
| 6793 | * a mapped sgl. | 7632 | sglq = NULL; |
| 6794 | */ | ||
| 6795 | } else { | 7633 | } else { |
| 6796 | /* This is a continuation of a commandi,(CX) so this | 7634 | /* |
| 7635 | * This is a continuation of a commandi,(CX) so this | ||
| 6797 | * sglq is on the active list | 7636 | * sglq is on the active list |
| 6798 | */ | 7637 | */ |
| 6799 | sglq = __lpfc_get_active_sglq(phba, piocb->sli4_xritag); | 7638 | sglq = __lpfc_get_active_sglq(phba, piocb->sli4_xritag); |
| @@ -6802,8 +7641,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
| 6802 | } | 7641 | } |
| 6803 | 7642 | ||
| 6804 | if (sglq) { | 7643 | if (sglq) { |
| 7644 | piocb->sli4_lxritag = sglq->sli4_lxritag; | ||
| 6805 | piocb->sli4_xritag = sglq->sli4_xritag; | 7645 | piocb->sli4_xritag = sglq->sli4_xritag; |
| 6806 | |||
| 6807 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) | 7646 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) |
| 6808 | return IOCB_ERROR; | 7647 | return IOCB_ERROR; |
| 6809 | } | 7648 | } |
| @@ -9799,7 +10638,12 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) | |||
| 9799 | break; | 10638 | break; |
| 9800 | case LPFC_WCQ: | 10639 | case LPFC_WCQ: |
| 9801 | while ((cqe = lpfc_sli4_cq_get(cq))) { | 10640 | while ((cqe = lpfc_sli4_cq_get(cq))) { |
| 9802 | workposted |= lpfc_sli4_sp_handle_cqe(phba, cq, cqe); | 10641 | if (cq->subtype == LPFC_FCP) |
| 10642 | workposted |= lpfc_sli4_fp_handle_wcqe(phba, cq, | ||
| 10643 | cqe); | ||
| 10644 | else | ||
| 10645 | workposted |= lpfc_sli4_sp_handle_cqe(phba, cq, | ||
| 10646 | cqe); | ||
| 9803 | if (!(++ecount % LPFC_GET_QE_REL_INT)) | 10647 | if (!(++ecount % LPFC_GET_QE_REL_INT)) |
| 9804 | lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); | 10648 | lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM); |
| 9805 | } | 10649 | } |
| @@ -11446,6 +12290,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
| 11446 | LPFC_MBOXQ_t *mbox; | 12290 | LPFC_MBOXQ_t *mbox; |
| 11447 | int rc; | 12291 | int rc; |
| 11448 | uint32_t shdr_status, shdr_add_status; | 12292 | uint32_t shdr_status, shdr_add_status; |
| 12293 | uint32_t mbox_tmo; | ||
| 11449 | union lpfc_sli4_cfg_shdr *shdr; | 12294 | union lpfc_sli4_cfg_shdr *shdr; |
| 11450 | 12295 | ||
| 11451 | if (xritag == NO_XRI) { | 12296 | if (xritag == NO_XRI) { |
| @@ -11479,8 +12324,10 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
| 11479 | cpu_to_le32(putPaddrHigh(pdma_phys_addr1)); | 12324 | cpu_to_le32(putPaddrHigh(pdma_phys_addr1)); |
| 11480 | if (!phba->sli4_hba.intr_enable) | 12325 | if (!phba->sli4_hba.intr_enable) |
| 11481 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 12326 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
| 11482 | else | 12327 | else { |
| 11483 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); | 12328 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); |
| 12329 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 12330 | } | ||
| 11484 | /* The IOCTL status is embedded in the mailbox subheader. */ | 12331 | /* The IOCTL status is embedded in the mailbox subheader. */ |
| 11485 | shdr = (union lpfc_sli4_cfg_shdr *) &post_sgl_pages->header.cfg_shdr; | 12332 | shdr = (union lpfc_sli4_cfg_shdr *) &post_sgl_pages->header.cfg_shdr; |
| 11486 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | 12333 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); |
| @@ -11498,6 +12345,76 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
| 11498 | } | 12345 | } |
| 11499 | 12346 | ||
| 11500 | /** | 12347 | /** |
| 12348 | * lpfc_sli4_init_rpi_hdrs - Post the rpi header memory region to the port | ||
| 12349 | * @phba: pointer to lpfc hba data structure. | ||
| 12350 | * | ||
| 12351 | * This routine is invoked to post rpi header templates to the | ||
| 12352 | * port for those SLI4 ports that do not support extents. This routine | ||
| 12353 | * posts a PAGE_SIZE memory region to the port to hold up to | ||
| 12354 | * PAGE_SIZE modulo 64 rpi context headers. This is an initialization routine | ||
| 12355 | * and should be called only when interrupts are disabled. | ||
| 12356 | * | ||
| 12357 | * Return codes | ||
| 12358 | * 0 - successful | ||
| 12359 | * -ERROR - otherwise. | ||
| 12360 | */ | ||
| 12361 | uint16_t | ||
| 12362 | lpfc_sli4_alloc_xri(struct lpfc_hba *phba) | ||
| 12363 | { | ||
| 12364 | unsigned long xri; | ||
| 12365 | |||
| 12366 | /* | ||
| 12367 | * Fetch the next logical xri. Because this index is logical, | ||
| 12368 | * the driver starts at 0 each time. | ||
| 12369 | */ | ||
| 12370 | spin_lock_irq(&phba->hbalock); | ||
| 12371 | xri = find_next_zero_bit(phba->sli4_hba.xri_bmask, | ||
| 12372 | phba->sli4_hba.max_cfg_param.max_xri, 0); | ||
| 12373 | if (xri >= phba->sli4_hba.max_cfg_param.max_xri) { | ||
| 12374 | spin_unlock_irq(&phba->hbalock); | ||
| 12375 | return NO_XRI; | ||
| 12376 | } else { | ||
| 12377 | set_bit(xri, phba->sli4_hba.xri_bmask); | ||
| 12378 | phba->sli4_hba.max_cfg_param.xri_used++; | ||
| 12379 | phba->sli4_hba.xri_count++; | ||
| 12380 | } | ||
| 12381 | |||
| 12382 | spin_unlock_irq(&phba->hbalock); | ||
| 12383 | return xri; | ||
| 12384 | } | ||
| 12385 | |||
| 12386 | /** | ||
| 12387 | * lpfc_sli4_free_xri - Release an xri for reuse. | ||
| 12388 | * @phba: pointer to lpfc hba data structure. | ||
| 12389 | * | ||
| 12390 | * This routine is invoked to release an xri to the pool of | ||
| 12391 | * available rpis maintained by the driver. | ||
| 12392 | **/ | ||
| 12393 | void | ||
| 12394 | __lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) | ||
| 12395 | { | ||
| 12396 | if (test_and_clear_bit(xri, phba->sli4_hba.xri_bmask)) { | ||
| 12397 | phba->sli4_hba.xri_count--; | ||
| 12398 | phba->sli4_hba.max_cfg_param.xri_used--; | ||
| 12399 | } | ||
| 12400 | } | ||
| 12401 | |||
| 12402 | /** | ||
| 12403 | * lpfc_sli4_free_xri - Release an xri for reuse. | ||
| 12404 | * @phba: pointer to lpfc hba data structure. | ||
| 12405 | * | ||
| 12406 | * This routine is invoked to release an xri to the pool of | ||
| 12407 | * available rpis maintained by the driver. | ||
| 12408 | **/ | ||
| 12409 | void | ||
| 12410 | lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) | ||
| 12411 | { | ||
| 12412 | spin_lock_irq(&phba->hbalock); | ||
| 12413 | __lpfc_sli4_free_xri(phba, xri); | ||
| 12414 | spin_unlock_irq(&phba->hbalock); | ||
| 12415 | } | ||
| 12416 | |||
| 12417 | /** | ||
| 11501 | * lpfc_sli4_next_xritag - Get an xritag for the io | 12418 | * lpfc_sli4_next_xritag - Get an xritag for the io |
| 11502 | * @phba: Pointer to HBA context object. | 12419 | * @phba: Pointer to HBA context object. |
| 11503 | * | 12420 | * |
| @@ -11510,30 +12427,23 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba, | |||
| 11510 | uint16_t | 12427 | uint16_t |
| 11511 | lpfc_sli4_next_xritag(struct lpfc_hba *phba) | 12428 | lpfc_sli4_next_xritag(struct lpfc_hba *phba) |
| 11512 | { | 12429 | { |
| 11513 | uint16_t xritag; | 12430 | uint16_t xri_index; |
| 11514 | 12431 | ||
| 11515 | spin_lock_irq(&phba->hbalock); | 12432 | xri_index = lpfc_sli4_alloc_xri(phba); |
| 11516 | xritag = phba->sli4_hba.next_xri; | 12433 | if (xri_index != NO_XRI) |
| 11517 | if ((xritag != (uint16_t) -1) && xritag < | 12434 | return xri_index; |
| 11518 | (phba->sli4_hba.max_cfg_param.max_xri | 12435 | |
| 11519 | + phba->sli4_hba.max_cfg_param.xri_base)) { | 12436 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
| 11520 | phba->sli4_hba.next_xri++; | ||
| 11521 | phba->sli4_hba.max_cfg_param.xri_used++; | ||
| 11522 | spin_unlock_irq(&phba->hbalock); | ||
| 11523 | return xritag; | ||
| 11524 | } | ||
| 11525 | spin_unlock_irq(&phba->hbalock); | ||
| 11526 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
| 11527 | "2004 Failed to allocate XRI.last XRITAG is %d" | 12437 | "2004 Failed to allocate XRI.last XRITAG is %d" |
| 11528 | " Max XRI is %d, Used XRI is %d\n", | 12438 | " Max XRI is %d, Used XRI is %d\n", |
| 11529 | phba->sli4_hba.next_xri, | 12439 | xri_index, |
| 11530 | phba->sli4_hba.max_cfg_param.max_xri, | 12440 | phba->sli4_hba.max_cfg_param.max_xri, |
| 11531 | phba->sli4_hba.max_cfg_param.xri_used); | 12441 | phba->sli4_hba.max_cfg_param.xri_used); |
| 11532 | return -1; | 12442 | return NO_XRI; |
| 11533 | } | 12443 | } |
| 11534 | 12444 | ||
| 11535 | /** | 12445 | /** |
| 11536 | * lpfc_sli4_post_sgl_list - post a block of sgl list to the firmware. | 12446 | * lpfc_sli4_post_els_sgl_list - post a block of ELS sgls to the port. |
| 11537 | * @phba: pointer to lpfc hba data structure. | 12447 | * @phba: pointer to lpfc hba data structure. |
| 11538 | * | 12448 | * |
| 11539 | * This routine is invoked to post a block of driver's sgl pages to the | 12449 | * This routine is invoked to post a block of driver's sgl pages to the |
| @@ -11542,7 +12452,7 @@ lpfc_sli4_next_xritag(struct lpfc_hba *phba) | |||
| 11542 | * stopped. | 12452 | * stopped. |
| 11543 | **/ | 12453 | **/ |
| 11544 | int | 12454 | int |
| 11545 | lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | 12455 | lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba) |
| 11546 | { | 12456 | { |
| 11547 | struct lpfc_sglq *sglq_entry; | 12457 | struct lpfc_sglq *sglq_entry; |
| 11548 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | 12458 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; |
| @@ -11551,7 +12461,7 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
| 11551 | LPFC_MBOXQ_t *mbox; | 12461 | LPFC_MBOXQ_t *mbox; |
| 11552 | uint32_t reqlen, alloclen, pg_pairs; | 12462 | uint32_t reqlen, alloclen, pg_pairs; |
| 11553 | uint32_t mbox_tmo; | 12463 | uint32_t mbox_tmo; |
| 11554 | uint16_t xritag_start = 0; | 12464 | uint16_t xritag_start = 0, lxri = 0; |
| 11555 | int els_xri_cnt, rc = 0; | 12465 | int els_xri_cnt, rc = 0; |
| 11556 | uint32_t shdr_status, shdr_add_status; | 12466 | uint32_t shdr_status, shdr_add_status; |
| 11557 | union lpfc_sli4_cfg_shdr *shdr; | 12467 | union lpfc_sli4_cfg_shdr *shdr; |
| @@ -11568,11 +12478,8 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
| 11568 | return -ENOMEM; | 12478 | return -ENOMEM; |
| 11569 | } | 12479 | } |
| 11570 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 12480 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 11571 | if (!mbox) { | 12481 | if (!mbox) |
| 11572 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 11573 | "2560 Failed to allocate mbox cmd memory\n"); | ||
| 11574 | return -ENOMEM; | 12482 | return -ENOMEM; |
| 11575 | } | ||
| 11576 | 12483 | ||
| 11577 | /* Allocate DMA memory and set up the non-embedded mailbox command */ | 12484 | /* Allocate DMA memory and set up the non-embedded mailbox command */ |
| 11578 | alloclen = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, | 12485 | alloclen = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE, |
| @@ -11587,15 +12494,30 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
| 11587 | lpfc_sli4_mbox_cmd_free(phba, mbox); | 12494 | lpfc_sli4_mbox_cmd_free(phba, mbox); |
| 11588 | return -ENOMEM; | 12495 | return -ENOMEM; |
| 11589 | } | 12496 | } |
| 11590 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
| 11591 | viraddr = mbox->sge_array->addr[0]; | ||
| 11592 | |||
| 11593 | /* Set up the SGL pages in the non-embedded DMA pages */ | 12497 | /* Set up the SGL pages in the non-embedded DMA pages */ |
| 12498 | viraddr = mbox->sge_array->addr[0]; | ||
| 11594 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | 12499 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; |
| 11595 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | 12500 | sgl_pg_pairs = &sgl->sgl_pg_pairs; |
| 11596 | 12501 | ||
| 11597 | for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) { | 12502 | for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) { |
| 11598 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs]; | 12503 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs]; |
| 12504 | |||
| 12505 | /* | ||
| 12506 | * Assign the sglq a physical xri only if the driver has not | ||
| 12507 | * initialized those resources. A port reset only needs | ||
| 12508 | * the sglq's posted. | ||
| 12509 | */ | ||
| 12510 | if (bf_get(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags) != | ||
| 12511 | LPFC_XRI_RSRC_RDY) { | ||
| 12512 | lxri = lpfc_sli4_next_xritag(phba); | ||
| 12513 | if (lxri == NO_XRI) { | ||
| 12514 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12515 | return -ENOMEM; | ||
| 12516 | } | ||
| 12517 | sglq_entry->sli4_lxritag = lxri; | ||
| 12518 | sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | ||
| 12519 | } | ||
| 12520 | |||
| 11599 | /* Set up the sge entry */ | 12521 | /* Set up the sge entry */ |
| 11600 | sgl_pg_pairs->sgl_pg0_addr_lo = | 12522 | sgl_pg_pairs->sgl_pg0_addr_lo = |
| 11601 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); | 12523 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); |
| @@ -11605,16 +12527,17 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
| 11605 | cpu_to_le32(putPaddrLow(0)); | 12527 | cpu_to_le32(putPaddrLow(0)); |
| 11606 | sgl_pg_pairs->sgl_pg1_addr_hi = | 12528 | sgl_pg_pairs->sgl_pg1_addr_hi = |
| 11607 | cpu_to_le32(putPaddrHigh(0)); | 12529 | cpu_to_le32(putPaddrHigh(0)); |
| 12530 | |||
| 11608 | /* Keep the first xritag on the list */ | 12531 | /* Keep the first xritag on the list */ |
| 11609 | if (pg_pairs == 0) | 12532 | if (pg_pairs == 0) |
| 11610 | xritag_start = sglq_entry->sli4_xritag; | 12533 | xritag_start = sglq_entry->sli4_xritag; |
| 11611 | sgl_pg_pairs++; | 12534 | sgl_pg_pairs++; |
| 11612 | } | 12535 | } |
| 12536 | |||
| 12537 | /* Complete initialization and perform endian conversion. */ | ||
| 11613 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); | 12538 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); |
| 11614 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt); | 12539 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt); |
| 11615 | /* Perform endian conversion if necessary */ | ||
| 11616 | sgl->word0 = cpu_to_le32(sgl->word0); | 12540 | sgl->word0 = cpu_to_le32(sgl->word0); |
| 11617 | |||
| 11618 | if (!phba->sli4_hba.intr_enable) | 12541 | if (!phba->sli4_hba.intr_enable) |
| 11619 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | 12542 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); |
| 11620 | else { | 12543 | else { |
| @@ -11633,6 +12556,181 @@ lpfc_sli4_post_sgl_list(struct lpfc_hba *phba) | |||
| 11633 | shdr_status, shdr_add_status, rc); | 12556 | shdr_status, shdr_add_status, rc); |
| 11634 | rc = -ENXIO; | 12557 | rc = -ENXIO; |
| 11635 | } | 12558 | } |
| 12559 | |||
| 12560 | if (rc == 0) | ||
| 12561 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
| 12562 | LPFC_XRI_RSRC_RDY); | ||
| 12563 | return rc; | ||
| 12564 | } | ||
| 12565 | |||
| 12566 | /** | ||
| 12567 | * lpfc_sli4_post_els_sgl_list_ext - post a block of ELS sgls to the port. | ||
| 12568 | * @phba: pointer to lpfc hba data structure. | ||
| 12569 | * | ||
| 12570 | * This routine is invoked to post a block of driver's sgl pages to the | ||
| 12571 | * HBA using non-embedded mailbox command. No Lock is held. This routine | ||
| 12572 | * is only called when the driver is loading and after all IO has been | ||
| 12573 | * stopped. | ||
| 12574 | **/ | ||
| 12575 | int | ||
| 12576 | lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba) | ||
| 12577 | { | ||
| 12578 | struct lpfc_sglq *sglq_entry; | ||
| 12579 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | ||
| 12580 | struct sgl_page_pairs *sgl_pg_pairs; | ||
| 12581 | void *viraddr; | ||
| 12582 | LPFC_MBOXQ_t *mbox; | ||
| 12583 | uint32_t reqlen, alloclen, index; | ||
| 12584 | uint32_t mbox_tmo; | ||
| 12585 | uint16_t rsrc_start, rsrc_size, els_xri_cnt; | ||
| 12586 | uint16_t xritag_start = 0, lxri = 0; | ||
| 12587 | struct lpfc_rsrc_blks *rsrc_blk; | ||
| 12588 | int cnt, ttl_cnt, rc = 0; | ||
| 12589 | int loop_cnt; | ||
| 12590 | uint32_t shdr_status, shdr_add_status; | ||
| 12591 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 12592 | |||
| 12593 | /* The number of sgls to be posted */ | ||
| 12594 | els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba); | ||
| 12595 | |||
| 12596 | reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) + | ||
| 12597 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
| 12598 | if (reqlen > SLI4_PAGE_SIZE) { | ||
| 12599 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 12600 | "2989 Block sgl registration required DMA " | ||
| 12601 | "size (%d) great than a page\n", reqlen); | ||
| 12602 | return -ENOMEM; | ||
| 12603 | } | ||
| 12604 | |||
| 12605 | cnt = 0; | ||
| 12606 | ttl_cnt = 0; | ||
| 12607 | list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list, | ||
| 12608 | list) { | ||
| 12609 | rsrc_start = rsrc_blk->rsrc_start; | ||
| 12610 | rsrc_size = rsrc_blk->rsrc_size; | ||
| 12611 | |||
| 12612 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 12613 | "3014 Working ELS Extent start %d, cnt %d\n", | ||
| 12614 | rsrc_start, rsrc_size); | ||
| 12615 | |||
| 12616 | loop_cnt = min(els_xri_cnt, rsrc_size); | ||
| 12617 | if (ttl_cnt + loop_cnt >= els_xri_cnt) { | ||
| 12618 | loop_cnt = els_xri_cnt - ttl_cnt; | ||
| 12619 | ttl_cnt = els_xri_cnt; | ||
| 12620 | } | ||
| 12621 | |||
| 12622 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 12623 | if (!mbox) | ||
| 12624 | return -ENOMEM; | ||
| 12625 | /* | ||
| 12626 | * Allocate DMA memory and set up the non-embedded mailbox | ||
| 12627 | * command. | ||
| 12628 | */ | ||
| 12629 | alloclen = lpfc_sli4_config(phba, mbox, | ||
| 12630 | LPFC_MBOX_SUBSYSTEM_FCOE, | ||
| 12631 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, | ||
| 12632 | reqlen, LPFC_SLI4_MBX_NEMBED); | ||
| 12633 | if (alloclen < reqlen) { | ||
| 12634 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 12635 | "2987 Allocated DMA memory size (%d) " | ||
| 12636 | "is less than the requested DMA memory " | ||
| 12637 | "size (%d)\n", alloclen, reqlen); | ||
| 12638 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12639 | return -ENOMEM; | ||
| 12640 | } | ||
| 12641 | |||
| 12642 | /* Set up the SGL pages in the non-embedded DMA pages */ | ||
| 12643 | viraddr = mbox->sge_array->addr[0]; | ||
| 12644 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | ||
| 12645 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | ||
| 12646 | |||
| 12647 | /* | ||
| 12648 | * The starting resource may not begin at zero. Control | ||
| 12649 | * the loop variants via the block resource parameters, | ||
| 12650 | * but handle the sge pointers with a zero-based index | ||
| 12651 | * that doesn't get reset per loop pass. | ||
| 12652 | */ | ||
| 12653 | for (index = rsrc_start; | ||
| 12654 | index < rsrc_start + loop_cnt; | ||
| 12655 | index++) { | ||
| 12656 | sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[cnt]; | ||
| 12657 | |||
| 12658 | /* | ||
| 12659 | * Assign the sglq a physical xri only if the driver | ||
| 12660 | * has not initialized those resources. A port reset | ||
| 12661 | * only needs the sglq's posted. | ||
| 12662 | */ | ||
| 12663 | if (bf_get(lpfc_xri_rsrc_rdy, | ||
| 12664 | &phba->sli4_hba.sli4_flags) != | ||
| 12665 | LPFC_XRI_RSRC_RDY) { | ||
| 12666 | lxri = lpfc_sli4_next_xritag(phba); | ||
| 12667 | if (lxri == NO_XRI) { | ||
| 12668 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12669 | rc = -ENOMEM; | ||
| 12670 | goto err_exit; | ||
| 12671 | } | ||
| 12672 | sglq_entry->sli4_lxritag = lxri; | ||
| 12673 | sglq_entry->sli4_xritag = | ||
| 12674 | phba->sli4_hba.xri_ids[lxri]; | ||
| 12675 | } | ||
| 12676 | |||
| 12677 | /* Set up the sge entry */ | ||
| 12678 | sgl_pg_pairs->sgl_pg0_addr_lo = | ||
| 12679 | cpu_to_le32(putPaddrLow(sglq_entry->phys)); | ||
| 12680 | sgl_pg_pairs->sgl_pg0_addr_hi = | ||
| 12681 | cpu_to_le32(putPaddrHigh(sglq_entry->phys)); | ||
| 12682 | sgl_pg_pairs->sgl_pg1_addr_lo = | ||
| 12683 | cpu_to_le32(putPaddrLow(0)); | ||
| 12684 | sgl_pg_pairs->sgl_pg1_addr_hi = | ||
| 12685 | cpu_to_le32(putPaddrHigh(0)); | ||
| 12686 | |||
| 12687 | /* Track the starting physical XRI for the mailbox. */ | ||
| 12688 | if (index == rsrc_start) | ||
| 12689 | xritag_start = sglq_entry->sli4_xritag; | ||
| 12690 | sgl_pg_pairs++; | ||
| 12691 | cnt++; | ||
| 12692 | } | ||
| 12693 | |||
| 12694 | /* Complete initialization and perform endian conversion. */ | ||
| 12695 | rsrc_blk->rsrc_used += loop_cnt; | ||
| 12696 | bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start); | ||
| 12697 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, loop_cnt); | ||
| 12698 | sgl->word0 = cpu_to_le32(sgl->word0); | ||
| 12699 | |||
| 12700 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 12701 | "3015 Post ELS Extent SGL, start %d, " | ||
| 12702 | "cnt %d, used %d\n", | ||
| 12703 | xritag_start, loop_cnt, rsrc_blk->rsrc_used); | ||
| 12704 | if (!phba->sli4_hba.intr_enable) | ||
| 12705 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 12706 | else { | ||
| 12707 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 12708 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 12709 | } | ||
| 12710 | shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; | ||
| 12711 | shdr_status = bf_get(lpfc_mbox_hdr_status, | ||
| 12712 | &shdr->response); | ||
| 12713 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
| 12714 | &shdr->response); | ||
| 12715 | if (rc != MBX_TIMEOUT) | ||
| 12716 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12717 | if (shdr_status || shdr_add_status || rc) { | ||
| 12718 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
| 12719 | "2988 POST_SGL_BLOCK mailbox " | ||
| 12720 | "command failed status x%x " | ||
| 12721 | "add_status x%x mbx status x%x\n", | ||
| 12722 | shdr_status, shdr_add_status, rc); | ||
| 12723 | rc = -ENXIO; | ||
| 12724 | goto err_exit; | ||
| 12725 | } | ||
| 12726 | if (ttl_cnt >= els_xri_cnt) | ||
| 12727 | break; | ||
| 12728 | } | ||
| 12729 | |||
| 12730 | err_exit: | ||
| 12731 | if (rc == 0) | ||
| 12732 | bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
| 12733 | LPFC_XRI_RSRC_RDY); | ||
| 11636 | return rc; | 12734 | return rc; |
| 11637 | } | 12735 | } |
| 11638 | 12736 | ||
| @@ -11693,6 +12791,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, | |||
| 11693 | lpfc_sli4_mbox_cmd_free(phba, mbox); | 12791 | lpfc_sli4_mbox_cmd_free(phba, mbox); |
| 11694 | return -ENOMEM; | 12792 | return -ENOMEM; |
| 11695 | } | 12793 | } |
| 12794 | |||
| 11696 | /* Get the first SGE entry from the non-embedded DMA memory */ | 12795 | /* Get the first SGE entry from the non-embedded DMA memory */ |
| 11697 | viraddr = mbox->sge_array->addr[0]; | 12796 | viraddr = mbox->sge_array->addr[0]; |
| 11698 | 12797 | ||
| @@ -11748,6 +12847,169 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, | |||
| 11748 | } | 12847 | } |
| 11749 | 12848 | ||
| 11750 | /** | 12849 | /** |
| 12850 | * lpfc_sli4_post_scsi_sgl_blk_ext - post a block of scsi sgls to the port. | ||
| 12851 | * @phba: pointer to lpfc hba data structure. | ||
| 12852 | * @sblist: pointer to scsi buffer list. | ||
| 12853 | * @count: number of scsi buffers on the list. | ||
| 12854 | * | ||
| 12855 | * This routine is invoked to post a block of @count scsi sgl pages from a | ||
| 12856 | * SCSI buffer list @sblist to the HBA using non-embedded mailbox command. | ||
| 12857 | * No Lock is held. | ||
| 12858 | * | ||
| 12859 | **/ | ||
| 12860 | int | ||
| 12861 | lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist, | ||
| 12862 | int cnt) | ||
| 12863 | { | ||
| 12864 | struct lpfc_scsi_buf *psb = NULL; | ||
| 12865 | struct lpfc_mbx_post_uembed_sgl_page1 *sgl; | ||
| 12866 | struct sgl_page_pairs *sgl_pg_pairs; | ||
| 12867 | void *viraddr; | ||
| 12868 | LPFC_MBOXQ_t *mbox; | ||
| 12869 | uint32_t reqlen, alloclen, pg_pairs; | ||
| 12870 | uint32_t mbox_tmo; | ||
| 12871 | uint16_t xri_start = 0, scsi_xri_start; | ||
| 12872 | uint16_t rsrc_range; | ||
| 12873 | int rc = 0, avail_cnt; | ||
| 12874 | uint32_t shdr_status, shdr_add_status; | ||
| 12875 | dma_addr_t pdma_phys_bpl1; | ||
| 12876 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 12877 | struct lpfc_rsrc_blks *rsrc_blk; | ||
| 12878 | uint32_t xri_cnt = 0; | ||
| 12879 | |||
| 12880 | /* Calculate the total requested length of the dma memory */ | ||
| 12881 | reqlen = cnt * sizeof(struct sgl_page_pairs) + | ||
| 12882 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
| 12883 | if (reqlen > SLI4_PAGE_SIZE) { | ||
| 12884 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
| 12885 | "2932 Block sgl registration required DMA " | ||
| 12886 | "size (%d) great than a page\n", reqlen); | ||
| 12887 | return -ENOMEM; | ||
| 12888 | } | ||
| 12889 | |||
| 12890 | /* | ||
| 12891 | * The use of extents requires the driver to post the sgl headers | ||
| 12892 | * in multiple postings to meet the contiguous resource assignment. | ||
| 12893 | */ | ||
| 12894 | psb = list_prepare_entry(psb, sblist, list); | ||
| 12895 | scsi_xri_start = phba->sli4_hba.scsi_xri_start; | ||
| 12896 | list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list, | ||
| 12897 | list) { | ||
| 12898 | rsrc_range = rsrc_blk->rsrc_start + rsrc_blk->rsrc_size; | ||
| 12899 | if (rsrc_range < scsi_xri_start) | ||
| 12900 | continue; | ||
| 12901 | else if (rsrc_blk->rsrc_used >= rsrc_blk->rsrc_size) | ||
| 12902 | continue; | ||
| 12903 | else | ||
| 12904 | avail_cnt = rsrc_blk->rsrc_size - rsrc_blk->rsrc_used; | ||
| 12905 | |||
| 12906 | reqlen = (avail_cnt * sizeof(struct sgl_page_pairs)) + | ||
| 12907 | sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t); | ||
| 12908 | /* | ||
| 12909 | * Allocate DMA memory and set up the non-embedded mailbox | ||
| 12910 | * command. The mbox is used to post an SGL page per loop | ||
| 12911 | * but the DMA memory has a use-once semantic so the mailbox | ||
| 12912 | * is used and freed per loop pass. | ||
| 12913 | */ | ||
| 12914 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 12915 | if (!mbox) { | ||
| 12916 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 12917 | "2933 Failed to allocate mbox cmd " | ||
| 12918 | "memory\n"); | ||
| 12919 | return -ENOMEM; | ||
| 12920 | } | ||
| 12921 | alloclen = lpfc_sli4_config(phba, mbox, | ||
| 12922 | LPFC_MBOX_SUBSYSTEM_FCOE, | ||
| 12923 | LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES, | ||
| 12924 | reqlen, | ||
| 12925 | LPFC_SLI4_MBX_NEMBED); | ||
| 12926 | if (alloclen < reqlen) { | ||
| 12927 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 12928 | "2934 Allocated DMA memory size (%d) " | ||
| 12929 | "is less than the requested DMA memory " | ||
| 12930 | "size (%d)\n", alloclen, reqlen); | ||
| 12931 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12932 | return -ENOMEM; | ||
| 12933 | } | ||
| 12934 | |||
| 12935 | /* Get the first SGE entry from the non-embedded DMA memory */ | ||
| 12936 | viraddr = mbox->sge_array->addr[0]; | ||
| 12937 | |||
| 12938 | /* Set up the SGL pages in the non-embedded DMA pages */ | ||
| 12939 | sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr; | ||
| 12940 | sgl_pg_pairs = &sgl->sgl_pg_pairs; | ||
| 12941 | |||
| 12942 | /* pg_pairs tracks posted SGEs per loop iteration. */ | ||
| 12943 | pg_pairs = 0; | ||
| 12944 | list_for_each_entry_continue(psb, sblist, list) { | ||
| 12945 | /* Set up the sge entry */ | ||
| 12946 | sgl_pg_pairs->sgl_pg0_addr_lo = | ||
| 12947 | cpu_to_le32(putPaddrLow(psb->dma_phys_bpl)); | ||
| 12948 | sgl_pg_pairs->sgl_pg0_addr_hi = | ||
| 12949 | cpu_to_le32(putPaddrHigh(psb->dma_phys_bpl)); | ||
| 12950 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | ||
| 12951 | pdma_phys_bpl1 = psb->dma_phys_bpl + | ||
| 12952 | SGL_PAGE_SIZE; | ||
| 12953 | else | ||
| 12954 | pdma_phys_bpl1 = 0; | ||
| 12955 | sgl_pg_pairs->sgl_pg1_addr_lo = | ||
| 12956 | cpu_to_le32(putPaddrLow(pdma_phys_bpl1)); | ||
| 12957 | sgl_pg_pairs->sgl_pg1_addr_hi = | ||
| 12958 | cpu_to_le32(putPaddrHigh(pdma_phys_bpl1)); | ||
| 12959 | /* Keep the first xri for this extent. */ | ||
| 12960 | if (pg_pairs == 0) | ||
| 12961 | xri_start = psb->cur_iocbq.sli4_xritag; | ||
| 12962 | sgl_pg_pairs++; | ||
| 12963 | pg_pairs++; | ||
| 12964 | xri_cnt++; | ||
| 12965 | |||
| 12966 | /* | ||
| 12967 | * Track two exit conditions - the loop has constructed | ||
| 12968 | * all of the caller's SGE pairs or all available | ||
| 12969 | * resource IDs in this extent are consumed. | ||
| 12970 | */ | ||
| 12971 | if ((xri_cnt == cnt) || (pg_pairs >= avail_cnt)) | ||
| 12972 | break; | ||
| 12973 | } | ||
| 12974 | rsrc_blk->rsrc_used += pg_pairs; | ||
| 12975 | bf_set(lpfc_post_sgl_pages_xri, sgl, xri_start); | ||
| 12976 | bf_set(lpfc_post_sgl_pages_xricnt, sgl, pg_pairs); | ||
| 12977 | |||
| 12978 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 12979 | "3016 Post SCSI Extent SGL, start %d, cnt %d " | ||
| 12980 | "blk use %d\n", | ||
| 12981 | xri_start, pg_pairs, rsrc_blk->rsrc_used); | ||
| 12982 | /* Perform endian conversion if necessary */ | ||
| 12983 | sgl->word0 = cpu_to_le32(sgl->word0); | ||
| 12984 | if (!phba->sli4_hba.intr_enable) | ||
| 12985 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 12986 | else { | ||
| 12987 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 12988 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 12989 | } | ||
| 12990 | shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr; | ||
| 12991 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 12992 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
| 12993 | &shdr->response); | ||
| 12994 | if (rc != MBX_TIMEOUT) | ||
| 12995 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
| 12996 | if (shdr_status || shdr_add_status || rc) { | ||
| 12997 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
| 12998 | "2935 POST_SGL_BLOCK mailbox command " | ||
| 12999 | "failed status x%x add_status x%x " | ||
| 13000 | "mbx status x%x\n", | ||
| 13001 | shdr_status, shdr_add_status, rc); | ||
| 13002 | return -ENXIO; | ||
| 13003 | } | ||
| 13004 | |||
| 13005 | /* Post only what is requested. */ | ||
| 13006 | if (xri_cnt >= cnt) | ||
| 13007 | break; | ||
| 13008 | } | ||
| 13009 | return rc; | ||
| 13010 | } | ||
| 13011 | |||
| 13012 | /** | ||
| 11751 | * lpfc_fc_frame_check - Check that this frame is a valid frame to handle | 13013 | * lpfc_fc_frame_check - Check that this frame is a valid frame to handle |
| 11752 | * @phba: pointer to lpfc_hba struct that the frame was received on | 13014 | * @phba: pointer to lpfc_hba struct that the frame was received on |
| 11753 | * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) | 13015 | * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) |
| @@ -12137,6 +13399,28 @@ lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, | |||
| 12137 | } | 13399 | } |
| 12138 | 13400 | ||
| 12139 | /** | 13401 | /** |
| 13402 | * lpfc_sli4_xri_inrange - check xri is in range of xris owned by driver. | ||
| 13403 | * @phba: Pointer to HBA context object. | ||
| 13404 | * @xri: xri id in transaction. | ||
| 13405 | * | ||
| 13406 | * This function validates the xri maps to the known range of XRIs allocated an | ||
| 13407 | * used by the driver. | ||
| 13408 | **/ | ||
| 13409 | static uint16_t | ||
| 13410 | lpfc_sli4_xri_inrange(struct lpfc_hba *phba, | ||
| 13411 | uint16_t xri) | ||
| 13412 | { | ||
| 13413 | int i; | ||
| 13414 | |||
| 13415 | for (i = 0; i < phba->sli4_hba.max_cfg_param.max_xri; i++) { | ||
| 13416 | if (xri == phba->sli4_hba.xri_ids[i]) | ||
| 13417 | return i; | ||
| 13418 | } | ||
| 13419 | return NO_XRI; | ||
| 13420 | } | ||
| 13421 | |||
| 13422 | |||
| 13423 | /** | ||
| 12140 | * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort | 13424 | * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort |
| 12141 | * @phba: Pointer to HBA context object. | 13425 | * @phba: Pointer to HBA context object. |
| 12142 | * @fc_hdr: pointer to a FC frame header. | 13426 | * @fc_hdr: pointer to a FC frame header. |
| @@ -12169,9 +13453,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
| 12169 | "SID:x%x\n", oxid, sid); | 13453 | "SID:x%x\n", oxid, sid); |
| 12170 | return; | 13454 | return; |
| 12171 | } | 13455 | } |
| 12172 | if (rxid >= phba->sli4_hba.max_cfg_param.xri_base | 13456 | if (lpfc_sli4_xri_inrange(phba, rxid)) |
| 12173 | && rxid <= (phba->sli4_hba.max_cfg_param.max_xri | ||
| 12174 | + phba->sli4_hba.max_cfg_param.xri_base)) | ||
| 12175 | lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); | 13457 | lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); |
| 12176 | 13458 | ||
| 12177 | /* Allocate buffer for rsp iocb */ | 13459 | /* Allocate buffer for rsp iocb */ |
| @@ -12194,12 +13476,13 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba, | |||
| 12194 | icmd->ulpBdeCount = 0; | 13476 | icmd->ulpBdeCount = 0; |
| 12195 | icmd->ulpLe = 1; | 13477 | icmd->ulpLe = 1; |
| 12196 | icmd->ulpClass = CLASS3; | 13478 | icmd->ulpClass = CLASS3; |
| 12197 | icmd->ulpContext = ndlp->nlp_rpi; | 13479 | icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; |
| 12198 | ctiocb->context1 = ndlp; | 13480 | ctiocb->context1 = ndlp; |
| 12199 | 13481 | ||
| 12200 | ctiocb->iocb_cmpl = NULL; | 13482 | ctiocb->iocb_cmpl = NULL; |
| 12201 | ctiocb->vport = phba->pport; | 13483 | ctiocb->vport = phba->pport; |
| 12202 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; | 13484 | ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; |
| 13485 | ctiocb->sli4_lxritag = NO_XRI; | ||
| 12203 | ctiocb->sli4_xritag = NO_XRI; | 13486 | ctiocb->sli4_xritag = NO_XRI; |
| 12204 | 13487 | ||
| 12205 | /* If the oxid maps to the FCP XRI range or if it is out of range, | 13488 | /* If the oxid maps to the FCP XRI range or if it is out of range, |
| @@ -12380,8 +13663,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) | |||
| 12380 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; | 13663 | first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; |
| 12381 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; | 13664 | first_iocbq->iocb.ulpCommand = CMD_IOCB_RCV_SEQ64_CX; |
| 12382 | first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id); | 13665 | first_iocbq->iocb.ulpContext = be16_to_cpu(fc_hdr->fh_ox_id); |
| 12383 | first_iocbq->iocb.unsli3.rcvsli3.vpi = | 13666 | /* iocbq is prepped for internal consumption. Logical vpi. */ |
| 12384 | vport->vpi + vport->phba->vpi_base; | 13667 | first_iocbq->iocb.unsli3.rcvsli3.vpi = vport->vpi; |
| 12385 | /* put the first buffer into the first IOCBq */ | 13668 | /* put the first buffer into the first IOCBq */ |
| 12386 | first_iocbq->context2 = &seq_dmabuf->dbuf; | 13669 | first_iocbq->context2 = &seq_dmabuf->dbuf; |
| 12387 | first_iocbq->context3 = NULL; | 13670 | first_iocbq->context3 = NULL; |
| @@ -12461,7 +13744,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, | |||
| 12461 | &phba->sli.ring[LPFC_ELS_RING], | 13744 | &phba->sli.ring[LPFC_ELS_RING], |
| 12462 | iocbq, fc_hdr->fh_r_ctl, | 13745 | iocbq, fc_hdr->fh_r_ctl, |
| 12463 | fc_hdr->fh_type)) | 13746 | fc_hdr->fh_type)) |
| 12464 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | 13747 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
| 12465 | "2540 Ring %d handler: unexpected Rctl " | 13748 | "2540 Ring %d handler: unexpected Rctl " |
| 12466 | "x%x Type x%x received\n", | 13749 | "x%x Type x%x received\n", |
| 12467 | LPFC_ELS_RING, | 13750 | LPFC_ELS_RING, |
| @@ -12558,9 +13841,24 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) | |||
| 12558 | { | 13841 | { |
| 12559 | struct lpfc_rpi_hdr *rpi_page; | 13842 | struct lpfc_rpi_hdr *rpi_page; |
| 12560 | uint32_t rc = 0; | 13843 | uint32_t rc = 0; |
| 13844 | uint16_t lrpi = 0; | ||
| 13845 | |||
| 13846 | /* SLI4 ports that support extents do not require RPI headers. */ | ||
| 13847 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
| 13848 | goto exit; | ||
| 13849 | if (phba->sli4_hba.extents_in_use) | ||
| 13850 | return -EIO; | ||
| 12561 | 13851 | ||
| 12562 | /* Post all rpi memory regions to the port. */ | ||
| 12563 | list_for_each_entry(rpi_page, &phba->sli4_hba.lpfc_rpi_hdr_list, list) { | 13852 | list_for_each_entry(rpi_page, &phba->sli4_hba.lpfc_rpi_hdr_list, list) { |
| 13853 | /* | ||
| 13854 | * Assign the rpi headers a physical rpi only if the driver | ||
| 13855 | * has not initialized those resources. A port reset only | ||
| 13856 | * needs the headers posted. | ||
| 13857 | */ | ||
| 13858 | if (bf_get(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags) != | ||
| 13859 | LPFC_RPI_RSRC_RDY) | ||
| 13860 | rpi_page->start_rpi = phba->sli4_hba.rpi_ids[lrpi]; | ||
| 13861 | |||
| 12564 | rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); | 13862 | rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); |
| 12565 | if (rc != MBX_SUCCESS) { | 13863 | if (rc != MBX_SUCCESS) { |
| 12566 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 13864 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
| @@ -12571,6 +13869,9 @@ lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) | |||
| 12571 | } | 13869 | } |
| 12572 | } | 13870 | } |
| 12573 | 13871 | ||
| 13872 | exit: | ||
| 13873 | bf_set(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, | ||
| 13874 | LPFC_RPI_RSRC_RDY); | ||
| 12574 | return rc; | 13875 | return rc; |
| 12575 | } | 13876 | } |
| 12576 | 13877 | ||
| @@ -12594,10 +13895,15 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
| 12594 | LPFC_MBOXQ_t *mboxq; | 13895 | LPFC_MBOXQ_t *mboxq; |
| 12595 | struct lpfc_mbx_post_hdr_tmpl *hdr_tmpl; | 13896 | struct lpfc_mbx_post_hdr_tmpl *hdr_tmpl; |
| 12596 | uint32_t rc = 0; | 13897 | uint32_t rc = 0; |
| 12597 | uint32_t mbox_tmo; | ||
| 12598 | uint32_t shdr_status, shdr_add_status; | 13898 | uint32_t shdr_status, shdr_add_status; |
| 12599 | union lpfc_sli4_cfg_shdr *shdr; | 13899 | union lpfc_sli4_cfg_shdr *shdr; |
| 12600 | 13900 | ||
| 13901 | /* SLI4 ports that support extents do not require RPI headers. */ | ||
| 13902 | if (!phba->sli4_hba.rpi_hdrs_in_use) | ||
| 13903 | return rc; | ||
| 13904 | if (phba->sli4_hba.extents_in_use) | ||
| 13905 | return -EIO; | ||
| 13906 | |||
| 12601 | /* The port is notified of the header region via a mailbox command. */ | 13907 | /* The port is notified of the header region via a mailbox command. */ |
| 12602 | mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 13908 | mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
| 12603 | if (!mboxq) { | 13909 | if (!mboxq) { |
| @@ -12609,16 +13915,19 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
| 12609 | 13915 | ||
| 12610 | /* Post all rpi memory regions to the port. */ | 13916 | /* Post all rpi memory regions to the port. */ |
| 12611 | hdr_tmpl = &mboxq->u.mqe.un.hdr_tmpl; | 13917 | hdr_tmpl = &mboxq->u.mqe.un.hdr_tmpl; |
| 12612 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 12613 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | 13918 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, |
| 12614 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, | 13919 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, |
| 12615 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - | 13920 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - |
| 12616 | sizeof(struct lpfc_sli4_cfg_mhdr), | 13921 | sizeof(struct lpfc_sli4_cfg_mhdr), |
| 12617 | LPFC_SLI4_MBX_EMBED); | 13922 | LPFC_SLI4_MBX_EMBED); |
| 12618 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | 13923 | |
| 12619 | hdr_tmpl, rpi_page->page_count); | 13924 | |
| 13925 | /* Post the physical rpi to the port for this rpi header. */ | ||
| 12620 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, | 13926 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, |
| 12621 | rpi_page->start_rpi); | 13927 | rpi_page->start_rpi); |
| 13928 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | ||
| 13929 | hdr_tmpl, rpi_page->page_count); | ||
| 13930 | |||
| 12622 | hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys); | 13931 | hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys); |
| 12623 | hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys); | 13932 | hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys); |
| 12624 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | 13933 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); |
| @@ -12653,22 +13962,21 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
| 12653 | int | 13962 | int |
| 12654 | lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | 13963 | lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) |
| 12655 | { | 13964 | { |
| 12656 | int rpi; | 13965 | unsigned long rpi; |
| 12657 | uint16_t max_rpi, rpi_base, rpi_limit; | 13966 | uint16_t max_rpi, rpi_limit; |
| 12658 | uint16_t rpi_remaining; | 13967 | uint16_t rpi_remaining, lrpi = 0; |
| 12659 | struct lpfc_rpi_hdr *rpi_hdr; | 13968 | struct lpfc_rpi_hdr *rpi_hdr; |
| 12660 | 13969 | ||
| 12661 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | 13970 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; |
| 12662 | rpi_base = phba->sli4_hba.max_cfg_param.rpi_base; | ||
| 12663 | rpi_limit = phba->sli4_hba.next_rpi; | 13971 | rpi_limit = phba->sli4_hba.next_rpi; |
| 12664 | 13972 | ||
| 12665 | /* | 13973 | /* |
| 12666 | * The valid rpi range is not guaranteed to be zero-based. Start | 13974 | * Fetch the next logical rpi. Because this index is logical, |
| 12667 | * the search at the rpi_base as reported by the port. | 13975 | * the driver starts at 0 each time. |
| 12668 | */ | 13976 | */ |
| 12669 | spin_lock_irq(&phba->hbalock); | 13977 | spin_lock_irq(&phba->hbalock); |
| 12670 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, rpi_base); | 13978 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); |
| 12671 | if (rpi >= rpi_limit || rpi < rpi_base) | 13979 | if (rpi >= rpi_limit) |
| 12672 | rpi = LPFC_RPI_ALLOC_ERROR; | 13980 | rpi = LPFC_RPI_ALLOC_ERROR; |
| 12673 | else { | 13981 | else { |
| 12674 | set_bit(rpi, phba->sli4_hba.rpi_bmask); | 13982 | set_bit(rpi, phba->sli4_hba.rpi_bmask); |
| @@ -12678,7 +13986,7 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
| 12678 | 13986 | ||
| 12679 | /* | 13987 | /* |
| 12680 | * Don't try to allocate more rpi header regions if the device limit | 13988 | * Don't try to allocate more rpi header regions if the device limit |
| 12681 | * on available rpis max has been exhausted. | 13989 | * has been exhausted. |
| 12682 | */ | 13990 | */ |
| 12683 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && | 13991 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && |
| 12684 | (phba->sli4_hba.rpi_count >= max_rpi)) { | 13992 | (phba->sli4_hba.rpi_count >= max_rpi)) { |
| @@ -12687,13 +13995,21 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
| 12687 | } | 13995 | } |
| 12688 | 13996 | ||
| 12689 | /* | 13997 | /* |
| 13998 | * RPI header postings are not required for SLI4 ports capable of | ||
| 13999 | * extents. | ||
| 14000 | */ | ||
| 14001 | if (!phba->sli4_hba.rpi_hdrs_in_use) { | ||
| 14002 | spin_unlock_irq(&phba->hbalock); | ||
| 14003 | return rpi; | ||
| 14004 | } | ||
| 14005 | |||
| 14006 | /* | ||
| 12690 | * If the driver is running low on rpi resources, allocate another | 14007 | * If the driver is running low on rpi resources, allocate another |
| 12691 | * page now. Note that the next_rpi value is used because | 14008 | * page now. Note that the next_rpi value is used because |
| 12692 | * it represents how many are actually in use whereas max_rpi notes | 14009 | * it represents how many are actually in use whereas max_rpi notes |
| 12693 | * how many are supported max by the device. | 14010 | * how many are supported max by the device. |
| 12694 | */ | 14011 | */ |
| 12695 | rpi_remaining = phba->sli4_hba.next_rpi - rpi_base - | 14012 | rpi_remaining = phba->sli4_hba.next_rpi - phba->sli4_hba.rpi_count; |
| 12696 | phba->sli4_hba.rpi_count; | ||
| 12697 | spin_unlock_irq(&phba->hbalock); | 14013 | spin_unlock_irq(&phba->hbalock); |
| 12698 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { | 14014 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { |
| 12699 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | 14015 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); |
| @@ -12702,6 +14018,8 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
| 12702 | "2002 Error Could not grow rpi " | 14018 | "2002 Error Could not grow rpi " |
| 12703 | "count\n"); | 14019 | "count\n"); |
| 12704 | } else { | 14020 | } else { |
| 14021 | lrpi = rpi_hdr->start_rpi; | ||
| 14022 | rpi_hdr->start_rpi = phba->sli4_hba.rpi_ids[lrpi]; | ||
| 12705 | lpfc_sli4_post_rpi_hdr(phba, rpi_hdr); | 14023 | lpfc_sli4_post_rpi_hdr(phba, rpi_hdr); |
| 12706 | } | 14024 | } |
| 12707 | } | 14025 | } |
| @@ -12751,6 +14069,8 @@ void | |||
| 12751 | lpfc_sli4_remove_rpis(struct lpfc_hba *phba) | 14069 | lpfc_sli4_remove_rpis(struct lpfc_hba *phba) |
| 12752 | { | 14070 | { |
| 12753 | kfree(phba->sli4_hba.rpi_bmask); | 14071 | kfree(phba->sli4_hba.rpi_bmask); |
| 14072 | kfree(phba->sli4_hba.rpi_ids); | ||
| 14073 | bf_set(lpfc_rpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | ||
| 12754 | } | 14074 | } |
| 12755 | 14075 | ||
| 12756 | /** | 14076 | /** |
| @@ -13490,6 +14810,96 @@ out: | |||
| 13490 | } | 14810 | } |
| 13491 | 14811 | ||
| 13492 | /** | 14812 | /** |
| 14813 | * lpfc_wr_object - write an object to the firmware | ||
| 14814 | * @phba: HBA structure that indicates port to create a queue on. | ||
| 14815 | * @dmabuf_list: list of dmabufs to write to the port. | ||
| 14816 | * @size: the total byte value of the objects to write to the port. | ||
| 14817 | * @offset: the current offset to be used to start the transfer. | ||
| 14818 | * | ||
| 14819 | * This routine will create a wr_object mailbox command to send to the port. | ||
| 14820 | * the mailbox command will be constructed using the dma buffers described in | ||
| 14821 | * @dmabuf_list to create a list of BDEs. This routine will fill in as many | ||
| 14822 | * BDEs that the imbedded mailbox can support. The @offset variable will be | ||
| 14823 | * used to indicate the starting offset of the transfer and will also return | ||
| 14824 | * the offset after the write object mailbox has completed. @size is used to | ||
| 14825 | * determine the end of the object and whether the eof bit should be set. | ||
| 14826 | * | ||
| 14827 | * Return 0 is successful and offset will contain the the new offset to use | ||
| 14828 | * for the next write. | ||
| 14829 | * Return negative value for error cases. | ||
| 14830 | **/ | ||
| 14831 | int | ||
| 14832 | lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, | ||
| 14833 | uint32_t size, uint32_t *offset) | ||
| 14834 | { | ||
| 14835 | struct lpfc_mbx_wr_object *wr_object; | ||
| 14836 | LPFC_MBOXQ_t *mbox; | ||
| 14837 | int rc = 0, i = 0; | ||
| 14838 | uint32_t shdr_status, shdr_add_status; | ||
| 14839 | uint32_t mbox_tmo; | ||
| 14840 | union lpfc_sli4_cfg_shdr *shdr; | ||
| 14841 | struct lpfc_dmabuf *dmabuf; | ||
| 14842 | uint32_t written = 0; | ||
| 14843 | |||
| 14844 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
| 14845 | if (!mbox) | ||
| 14846 | return -ENOMEM; | ||
| 14847 | |||
| 14848 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
| 14849 | LPFC_MBOX_OPCODE_WRITE_OBJECT, | ||
| 14850 | sizeof(struct lpfc_mbx_wr_object) - | ||
| 14851 | sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED); | ||
| 14852 | |||
| 14853 | wr_object = (struct lpfc_mbx_wr_object *)&mbox->u.mqe.un.wr_object; | ||
| 14854 | wr_object->u.request.write_offset = *offset; | ||
| 14855 | sprintf((uint8_t *)wr_object->u.request.object_name, "/"); | ||
| 14856 | wr_object->u.request.object_name[0] = | ||
| 14857 | cpu_to_le32(wr_object->u.request.object_name[0]); | ||
| 14858 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 0); | ||
| 14859 | list_for_each_entry(dmabuf, dmabuf_list, list) { | ||
| 14860 | if (i >= LPFC_MBX_WR_CONFIG_MAX_BDE || written >= size) | ||
| 14861 | break; | ||
| 14862 | wr_object->u.request.bde[i].addrLow = putPaddrLow(dmabuf->phys); | ||
| 14863 | wr_object->u.request.bde[i].addrHigh = | ||
| 14864 | putPaddrHigh(dmabuf->phys); | ||
| 14865 | if (written + SLI4_PAGE_SIZE >= size) { | ||
| 14866 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
| 14867 | (size - written); | ||
| 14868 | written += (size - written); | ||
| 14869 | bf_set(lpfc_wr_object_eof, &wr_object->u.request, 1); | ||
| 14870 | } else { | ||
| 14871 | wr_object->u.request.bde[i].tus.f.bdeSize = | ||
| 14872 | SLI4_PAGE_SIZE; | ||
| 14873 | written += SLI4_PAGE_SIZE; | ||
| 14874 | } | ||
| 14875 | i++; | ||
| 14876 | } | ||
| 14877 | wr_object->u.request.bde_count = i; | ||
| 14878 | bf_set(lpfc_wr_object_write_length, &wr_object->u.request, written); | ||
| 14879 | if (!phba->sli4_hba.intr_enable) | ||
| 14880 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
| 14881 | else { | ||
| 14882 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
| 14883 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
| 14884 | } | ||
| 14885 | /* The IOCTL status is embedded in the mailbox subheader. */ | ||
| 14886 | shdr = (union lpfc_sli4_cfg_shdr *) &wr_object->header.cfg_shdr; | ||
| 14887 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
| 14888 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
| 14889 | if (rc != MBX_TIMEOUT) | ||
| 14890 | mempool_free(mbox, phba->mbox_mem_pool); | ||
| 14891 | if (shdr_status || shdr_add_status || rc) { | ||
| 14892 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 14893 | "3025 Write Object mailbox failed with " | ||
| 14894 | "status x%x add_status x%x, mbx status x%x\n", | ||
| 14895 | shdr_status, shdr_add_status, rc); | ||
| 14896 | rc = -ENXIO; | ||
| 14897 | } else | ||
| 14898 | *offset += wr_object->u.response.actual_write_length; | ||
| 14899 | return rc; | ||
| 14900 | } | ||
| 14901 | |||
| 14902 | /** | ||
| 13493 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. | 14903 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. |
| 13494 | * @vport: pointer to vport data structure. | 14904 | * @vport: pointer to vport data structure. |
| 13495 | * | 14905 | * |
| @@ -13644,7 +15054,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) | |||
| 13644 | * never happen | 15054 | * never happen |
| 13645 | */ | 15055 | */ |
| 13646 | sglq = __lpfc_clear_active_sglq(phba, | 15056 | sglq = __lpfc_clear_active_sglq(phba, |
| 13647 | sglq->sli4_xritag); | 15057 | sglq->sli4_lxritag); |
| 13648 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 15058 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
| 13649 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 15059 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
| 13650 | "2823 txq empty and txq_cnt is %d\n ", | 15060 | "2823 txq empty and txq_cnt is %d\n ", |
| @@ -13656,6 +15066,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) | |||
| 13656 | /* The xri and iocb resources secured, | 15066 | /* The xri and iocb resources secured, |
| 13657 | * attempt to issue request | 15067 | * attempt to issue request |
| 13658 | */ | 15068 | */ |
| 15069 | piocbq->sli4_lxritag = sglq->sli4_lxritag; | ||
| 13659 | piocbq->sli4_xritag = sglq->sli4_xritag; | 15070 | piocbq->sli4_xritag = sglq->sli4_xritag; |
| 13660 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) | 15071 | if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) |
| 13661 | fail_msg = "to convert bpl to sgl"; | 15072 | fail_msg = "to convert bpl to sgl"; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 453577c21c14..a0075b0af142 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
| @@ -52,6 +52,7 @@ struct lpfc_iocbq { | |||
| 52 | struct list_head clist; | 52 | struct list_head clist; |
| 53 | struct list_head dlist; | 53 | struct list_head dlist; |
| 54 | uint16_t iotag; /* pre-assigned IO tag */ | 54 | uint16_t iotag; /* pre-assigned IO tag */ |
| 55 | uint16_t sli4_lxritag; /* logical pre-assigned XRI. */ | ||
| 55 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 56 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
| 56 | struct lpfc_cq_event cq_event; | 57 | struct lpfc_cq_event cq_event; |
| 57 | 58 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 1a3cbf88f2ce..4b1703554a26 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
| @@ -310,7 +310,6 @@ struct lpfc_max_cfg_param { | |||
| 310 | uint16_t vfi_base; | 310 | uint16_t vfi_base; |
| 311 | uint16_t vfi_used; | 311 | uint16_t vfi_used; |
| 312 | uint16_t max_fcfi; | 312 | uint16_t max_fcfi; |
| 313 | uint16_t fcfi_base; | ||
| 314 | uint16_t fcfi_used; | 313 | uint16_t fcfi_used; |
| 315 | uint16_t max_eq; | 314 | uint16_t max_eq; |
| 316 | uint16_t max_rq; | 315 | uint16_t max_rq; |
| @@ -365,6 +364,11 @@ struct lpfc_pc_sli4_params { | |||
| 365 | uint8_t rqv; | 364 | uint8_t rqv; |
| 366 | }; | 365 | }; |
| 367 | 366 | ||
| 367 | struct lpfc_iov { | ||
| 368 | uint32_t pf_number; | ||
| 369 | uint32_t vf_number; | ||
| 370 | }; | ||
| 371 | |||
| 368 | /* SLI4 HBA data structure entries */ | 372 | /* SLI4 HBA data structure entries */ |
| 369 | struct lpfc_sli4_hba { | 373 | struct lpfc_sli4_hba { |
| 370 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for | 374 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for |
| @@ -444,10 +448,13 @@ struct lpfc_sli4_hba { | |||
| 444 | uint32_t intr_enable; | 448 | uint32_t intr_enable; |
| 445 | struct lpfc_bmbx bmbx; | 449 | struct lpfc_bmbx bmbx; |
| 446 | struct lpfc_max_cfg_param max_cfg_param; | 450 | struct lpfc_max_cfg_param max_cfg_param; |
| 451 | uint16_t extents_in_use; /* must allocate resource extents. */ | ||
| 452 | uint16_t rpi_hdrs_in_use; /* must post rpi hdrs if set. */ | ||
| 447 | uint16_t next_xri; /* last_xri - max_cfg_param.xri_base = used */ | 453 | uint16_t next_xri; /* last_xri - max_cfg_param.xri_base = used */ |
| 448 | uint16_t next_rpi; | 454 | uint16_t next_rpi; |
| 449 | uint16_t scsi_xri_max; | 455 | uint16_t scsi_xri_max; |
| 450 | uint16_t scsi_xri_cnt; | 456 | uint16_t scsi_xri_cnt; |
| 457 | uint16_t scsi_xri_start; | ||
| 451 | struct list_head lpfc_free_sgl_list; | 458 | struct list_head lpfc_free_sgl_list; |
| 452 | struct list_head lpfc_sgl_list; | 459 | struct list_head lpfc_sgl_list; |
| 453 | struct lpfc_sglq **lpfc_els_sgl_array; | 460 | struct lpfc_sglq **lpfc_els_sgl_array; |
| @@ -458,7 +465,17 @@ struct lpfc_sli4_hba { | |||
| 458 | struct lpfc_sglq **lpfc_sglq_active_list; | 465 | struct lpfc_sglq **lpfc_sglq_active_list; |
| 459 | struct list_head lpfc_rpi_hdr_list; | 466 | struct list_head lpfc_rpi_hdr_list; |
| 460 | unsigned long *rpi_bmask; | 467 | unsigned long *rpi_bmask; |
| 468 | uint16_t *rpi_ids; | ||
| 461 | uint16_t rpi_count; | 469 | uint16_t rpi_count; |
| 470 | struct list_head lpfc_rpi_blk_list; | ||
| 471 | unsigned long *xri_bmask; | ||
| 472 | uint16_t *xri_ids; | ||
| 473 | uint16_t xri_count; | ||
| 474 | struct list_head lpfc_xri_blk_list; | ||
| 475 | unsigned long *vfi_bmask; | ||
| 476 | uint16_t *vfi_ids; | ||
| 477 | uint16_t vfi_count; | ||
| 478 | struct list_head lpfc_vfi_blk_list; | ||
| 462 | struct lpfc_sli4_flags sli4_flags; | 479 | struct lpfc_sli4_flags sli4_flags; |
| 463 | struct list_head sp_queue_event; | 480 | struct list_head sp_queue_event; |
| 464 | struct list_head sp_cqe_event_pool; | 481 | struct list_head sp_cqe_event_pool; |
| @@ -467,6 +484,7 @@ struct lpfc_sli4_hba { | |||
| 467 | struct list_head sp_els_xri_aborted_work_queue; | 484 | struct list_head sp_els_xri_aborted_work_queue; |
| 468 | struct list_head sp_unsol_work_queue; | 485 | struct list_head sp_unsol_work_queue; |
| 469 | struct lpfc_sli4_link link_state; | 486 | struct lpfc_sli4_link link_state; |
| 487 | struct lpfc_iov iov; | ||
| 470 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ | 488 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ |
| 471 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ | 489 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ |
| 472 | }; | 490 | }; |
| @@ -490,6 +508,7 @@ struct lpfc_sglq { | |||
| 490 | enum lpfc_sgl_state state; | 508 | enum lpfc_sgl_state state; |
| 491 | struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ | 509 | struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ |
| 492 | uint16_t iotag; /* pre-assigned IO tag */ | 510 | uint16_t iotag; /* pre-assigned IO tag */ |
| 511 | uint16_t sli4_lxritag; /* logical pre-assigned xri. */ | ||
| 493 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ | 512 | uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ |
| 494 | struct sli4_sge *sgl; /* pre-assigned SGL */ | 513 | struct sli4_sge *sgl; /* pre-assigned SGL */ |
| 495 | void *virt; /* virtual address. */ | 514 | void *virt; /* virtual address. */ |
| @@ -504,6 +523,13 @@ struct lpfc_rpi_hdr { | |||
| 504 | uint32_t start_rpi; | 523 | uint32_t start_rpi; |
| 505 | }; | 524 | }; |
| 506 | 525 | ||
| 526 | struct lpfc_rsrc_blks { | ||
| 527 | struct list_head list; | ||
| 528 | uint16_t rsrc_start; | ||
| 529 | uint16_t rsrc_size; | ||
| 530 | uint16_t rsrc_used; | ||
| 531 | }; | ||
| 532 | |||
| 507 | /* | 533 | /* |
| 508 | * SLI4 specific function prototypes | 534 | * SLI4 specific function prototypes |
| 509 | */ | 535 | */ |
| @@ -543,8 +569,11 @@ int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t); | |||
| 543 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); | 569 | int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *); |
| 544 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); | 570 | uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *); |
| 545 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); | 571 | int lpfc_sli4_post_async_mbox(struct lpfc_hba *); |
| 546 | int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba); | 572 | int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba); |
| 573 | int lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba); | ||
| 547 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); | 574 | int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int); |
| 575 | int lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *, struct list_head *, | ||
| 576 | int); | ||
| 548 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); | 577 | struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *); |
| 549 | struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *); | 578 | struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *); |
| 550 | void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *); | 579 | void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *); |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 30ba5440c67a..1feb551a57bc 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
| @@ -83,7 +83,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport, | |||
| 83 | static int | 83 | static int |
| 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) | 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) |
| 85 | { | 85 | { |
| 86 | int vpi; | 86 | unsigned long vpi; |
| 87 | 87 | ||
| 88 | spin_lock_irq(&phba->hbalock); | 88 | spin_lock_irq(&phba->hbalock); |
| 89 | /* Start at bit 1 because vpi zero is reserved for the physical port */ | 89 | /* Start at bit 1 because vpi zero is reserved for the physical port */ |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 046dcc672ec1..7370c084b178 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
| @@ -33,9 +33,9 @@ | |||
| 33 | /* | 33 | /* |
| 34 | * MegaRAID SAS Driver meta data | 34 | * MegaRAID SAS Driver meta data |
| 35 | */ | 35 | */ |
| 36 | #define MEGASAS_VERSION "00.00.05.34-rc1" | 36 | #define MEGASAS_VERSION "00.00.05.38-rc1" |
| 37 | #define MEGASAS_RELDATE "Feb. 24, 2011" | 37 | #define MEGASAS_RELDATE "May. 11, 2011" |
| 38 | #define MEGASAS_EXT_VERSION "Thu. Feb. 24 17:00:00 PDT 2011" | 38 | #define MEGASAS_EXT_VERSION "Wed. May. 11 17:00:00 PDT 2011" |
| 39 | 39 | ||
| 40 | /* | 40 | /* |
| 41 | * Device IDs | 41 | * Device IDs |
| @@ -76,8 +76,8 @@ | |||
| 76 | #define MFI_STATE_READY 0xB0000000 | 76 | #define MFI_STATE_READY 0xB0000000 |
| 77 | #define MFI_STATE_OPERATIONAL 0xC0000000 | 77 | #define MFI_STATE_OPERATIONAL 0xC0000000 |
| 78 | #define MFI_STATE_FAULT 0xF0000000 | 78 | #define MFI_STATE_FAULT 0xF0000000 |
| 79 | #define MFI_RESET_REQUIRED 0x00000001 | 79 | #define MFI_RESET_REQUIRED 0x00000001 |
| 80 | 80 | #define MFI_RESET_ADAPTER 0x00000002 | |
| 81 | #define MEGAMFI_FRAME_SIZE 64 | 81 | #define MEGAMFI_FRAME_SIZE 64 |
| 82 | 82 | ||
| 83 | /* | 83 | /* |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 89c623ebadbc..2d8cdce7b2f5 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | * | 19 | * |
| 20 | * FILE: megaraid_sas_base.c | 20 | * FILE: megaraid_sas_base.c |
| 21 | * Version : v00.00.05.34-rc1 | 21 | * Version : v00.00.05.38-rc1 |
| 22 | * | 22 | * |
| 23 | * Authors: LSI Corporation | 23 | * Authors: LSI Corporation |
| 24 | * Sreenivas Bagalkote | 24 | * Sreenivas Bagalkote |
| @@ -437,15 +437,18 @@ megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) | |||
| 437 | static int | 437 | static int |
| 438 | megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | 438 | megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) |
| 439 | { | 439 | { |
| 440 | u32 status; | 440 | u32 status, mfiStatus = 0; |
| 441 | |||
| 441 | /* | 442 | /* |
| 442 | * Check if it is our interrupt | 443 | * Check if it is our interrupt |
| 443 | */ | 444 | */ |
| 444 | status = readl(®s->outbound_intr_status); | 445 | status = readl(®s->outbound_intr_status); |
| 445 | 446 | ||
| 446 | if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { | 447 | if (status & MFI_REPLY_1078_MESSAGE_INTERRUPT) |
| 447 | return 0; | 448 | mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; |
| 448 | } | 449 | |
| 450 | if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) | ||
| 451 | mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; | ||
| 449 | 452 | ||
| 450 | /* | 453 | /* |
| 451 | * Clear the interrupt by writing back the same value | 454 | * Clear the interrupt by writing back the same value |
| @@ -455,8 +458,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | |||
| 455 | /* Dummy readl to force pci flush */ | 458 | /* Dummy readl to force pci flush */ |
| 456 | readl(®s->outbound_doorbell_clear); | 459 | readl(®s->outbound_doorbell_clear); |
| 457 | 460 | ||
| 458 | return 1; | 461 | return mfiStatus; |
| 459 | } | 462 | } |
| 463 | |||
| 460 | /** | 464 | /** |
| 461 | * megasas_fire_cmd_ppc - Sends command to the FW | 465 | * megasas_fire_cmd_ppc - Sends command to the FW |
| 462 | * @frame_phys_addr : Physical address of cmd | 466 | * @frame_phys_addr : Physical address of cmd |
| @@ -477,17 +481,6 @@ megasas_fire_cmd_ppc(struct megasas_instance *instance, | |||
| 477 | } | 481 | } |
| 478 | 482 | ||
| 479 | /** | 483 | /** |
| 480 | * megasas_adp_reset_ppc - For controller reset | ||
| 481 | * @regs: MFI register set | ||
| 482 | */ | ||
| 483 | static int | ||
| 484 | megasas_adp_reset_ppc(struct megasas_instance *instance, | ||
| 485 | struct megasas_register_set __iomem *regs) | ||
| 486 | { | ||
| 487 | return 0; | ||
| 488 | } | ||
| 489 | |||
| 490 | /** | ||
| 491 | * megasas_check_reset_ppc - For controller reset check | 484 | * megasas_check_reset_ppc - For controller reset check |
| 492 | * @regs: MFI register set | 485 | * @regs: MFI register set |
| 493 | */ | 486 | */ |
| @@ -495,8 +488,12 @@ static int | |||
| 495 | megasas_check_reset_ppc(struct megasas_instance *instance, | 488 | megasas_check_reset_ppc(struct megasas_instance *instance, |
| 496 | struct megasas_register_set __iomem *regs) | 489 | struct megasas_register_set __iomem *regs) |
| 497 | { | 490 | { |
| 491 | if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) | ||
| 492 | return 1; | ||
| 493 | |||
| 498 | return 0; | 494 | return 0; |
| 499 | } | 495 | } |
| 496 | |||
| 500 | static struct megasas_instance_template megasas_instance_template_ppc = { | 497 | static struct megasas_instance_template megasas_instance_template_ppc = { |
| 501 | 498 | ||
| 502 | .fire_cmd = megasas_fire_cmd_ppc, | 499 | .fire_cmd = megasas_fire_cmd_ppc, |
| @@ -504,7 +501,7 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
| 504 | .disable_intr = megasas_disable_intr_ppc, | 501 | .disable_intr = megasas_disable_intr_ppc, |
| 505 | .clear_intr = megasas_clear_intr_ppc, | 502 | .clear_intr = megasas_clear_intr_ppc, |
| 506 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, | 503 | .read_fw_status_reg = megasas_read_fw_status_reg_ppc, |
| 507 | .adp_reset = megasas_adp_reset_ppc, | 504 | .adp_reset = megasas_adp_reset_xscale, |
| 508 | .check_reset = megasas_check_reset_ppc, | 505 | .check_reset = megasas_check_reset_ppc, |
| 509 | .service_isr = megasas_isr, | 506 | .service_isr = megasas_isr, |
| 510 | .tasklet = megasas_complete_cmd_dpc, | 507 | .tasklet = megasas_complete_cmd_dpc, |
| @@ -620,6 +617,9 @@ static int | |||
| 620 | megasas_check_reset_skinny(struct megasas_instance *instance, | 617 | megasas_check_reset_skinny(struct megasas_instance *instance, |
| 621 | struct megasas_register_set __iomem *regs) | 618 | struct megasas_register_set __iomem *regs) |
| 622 | { | 619 | { |
| 620 | if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) | ||
| 621 | return 1; | ||
| 622 | |||
| 623 | return 0; | 623 | return 0; |
| 624 | } | 624 | } |
| 625 | 625 | ||
| @@ -3454,7 +3454,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 3454 | { | 3454 | { |
| 3455 | u32 max_sectors_1; | 3455 | u32 max_sectors_1; |
| 3456 | u32 max_sectors_2; | 3456 | u32 max_sectors_2; |
| 3457 | u32 tmp_sectors; | 3457 | u32 tmp_sectors, msix_enable; |
| 3458 | struct megasas_register_set __iomem *reg_set; | 3458 | struct megasas_register_set __iomem *reg_set; |
| 3459 | struct megasas_ctrl_info *ctrl_info; | 3459 | struct megasas_ctrl_info *ctrl_info; |
| 3460 | unsigned long bar_list; | 3460 | unsigned long bar_list; |
| @@ -3507,6 +3507,13 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
| 3507 | if (megasas_transition_to_ready(instance)) | 3507 | if (megasas_transition_to_ready(instance)) |
| 3508 | goto fail_ready_state; | 3508 | goto fail_ready_state; |
| 3509 | 3509 | ||
| 3510 | /* Check if MSI-X is supported while in ready state */ | ||
| 3511 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & | ||
| 3512 | 0x4000000) >> 0x1a; | ||
| 3513 | if (msix_enable && !msix_disable && | ||
| 3514 | !pci_enable_msix(instance->pdev, &instance->msixentry, 1)) | ||
| 3515 | instance->msi_flag = 1; | ||
| 3516 | |||
| 3510 | /* Get operational params, sge flags, send init cmd to controller */ | 3517 | /* Get operational params, sge flags, send init cmd to controller */ |
| 3511 | if (instance->instancet->init_adapter(instance)) | 3518 | if (instance->instancet->init_adapter(instance)) |
| 3512 | goto fail_init_adapter; | 3519 | goto fail_init_adapter; |
| @@ -4076,14 +4083,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4076 | else | 4083 | else |
| 4077 | INIT_WORK(&instance->work_init, process_fw_state_change_wq); | 4084 | INIT_WORK(&instance->work_init, process_fw_state_change_wq); |
| 4078 | 4085 | ||
| 4079 | /* Try to enable MSI-X */ | ||
| 4080 | if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) && | ||
| 4081 | (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) && | ||
| 4082 | (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) && | ||
| 4083 | !msix_disable && !pci_enable_msix(instance->pdev, | ||
| 4084 | &instance->msixentry, 1)) | ||
| 4085 | instance->msi_flag = 1; | ||
| 4086 | |||
| 4087 | /* | 4086 | /* |
| 4088 | * Initialize MFI Firmware | 4087 | * Initialize MFI Firmware |
| 4089 | */ | 4088 | */ |
| @@ -4116,6 +4115,14 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4116 | megasas_mgmt_info.max_index++; | 4115 | megasas_mgmt_info.max_index++; |
| 4117 | 4116 | ||
| 4118 | /* | 4117 | /* |
| 4118 | * Register with SCSI mid-layer | ||
| 4119 | */ | ||
| 4120 | if (megasas_io_attach(instance)) | ||
| 4121 | goto fail_io_attach; | ||
| 4122 | |||
| 4123 | instance->unload = 0; | ||
| 4124 | |||
| 4125 | /* | ||
| 4119 | * Initiate AEN (Asynchronous Event Notification) | 4126 | * Initiate AEN (Asynchronous Event Notification) |
| 4120 | */ | 4127 | */ |
| 4121 | if (megasas_start_aen(instance)) { | 4128 | if (megasas_start_aen(instance)) { |
| @@ -4123,13 +4130,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4123 | goto fail_start_aen; | 4130 | goto fail_start_aen; |
| 4124 | } | 4131 | } |
| 4125 | 4132 | ||
| 4126 | /* | ||
| 4127 | * Register with SCSI mid-layer | ||
| 4128 | */ | ||
| 4129 | if (megasas_io_attach(instance)) | ||
| 4130 | goto fail_io_attach; | ||
| 4131 | |||
| 4132 | instance->unload = 0; | ||
| 4133 | return 0; | 4133 | return 0; |
| 4134 | 4134 | ||
| 4135 | fail_start_aen: | 4135 | fail_start_aen: |
| @@ -4332,10 +4332,6 @@ megasas_resume(struct pci_dev *pdev) | |||
| 4332 | if (megasas_set_dma_mask(pdev)) | 4332 | if (megasas_set_dma_mask(pdev)) |
| 4333 | goto fail_set_dma_mask; | 4333 | goto fail_set_dma_mask; |
| 4334 | 4334 | ||
| 4335 | /* Now re-enable MSI-X */ | ||
| 4336 | if (instance->msi_flag) | ||
| 4337 | pci_enable_msix(instance->pdev, &instance->msixentry, 1); | ||
| 4338 | |||
| 4339 | /* | 4335 | /* |
| 4340 | * Initialize MFI Firmware | 4336 | * Initialize MFI Firmware |
| 4341 | */ | 4337 | */ |
| @@ -4348,6 +4344,10 @@ megasas_resume(struct pci_dev *pdev) | |||
| 4348 | if (megasas_transition_to_ready(instance)) | 4344 | if (megasas_transition_to_ready(instance)) |
| 4349 | goto fail_ready_state; | 4345 | goto fail_ready_state; |
| 4350 | 4346 | ||
| 4347 | /* Now re-enable MSI-X */ | ||
| 4348 | if (instance->msi_flag) | ||
| 4349 | pci_enable_msix(instance->pdev, &instance->msixentry, 1); | ||
| 4350 | |||
| 4351 | switch (instance->pdev->device) { | 4351 | switch (instance->pdev->device) { |
| 4352 | case PCI_DEVICE_ID_LSI_FUSION: | 4352 | case PCI_DEVICE_ID_LSI_FUSION: |
| 4353 | { | 4353 | { |
| @@ -4384,12 +4384,6 @@ megasas_resume(struct pci_dev *pdev) | |||
| 4384 | 4384 | ||
| 4385 | instance->instancet->enable_intr(instance->reg_set); | 4385 | instance->instancet->enable_intr(instance->reg_set); |
| 4386 | 4386 | ||
| 4387 | /* | ||
| 4388 | * Initiate AEN (Asynchronous Event Notification) | ||
| 4389 | */ | ||
| 4390 | if (megasas_start_aen(instance)) | ||
| 4391 | printk(KERN_ERR "megasas: Start AEN failed\n"); | ||
| 4392 | |||
| 4393 | /* Initialize the cmd completion timer */ | 4387 | /* Initialize the cmd completion timer */ |
| 4394 | if (poll_mode_io) | 4388 | if (poll_mode_io) |
| 4395 | megasas_start_timer(instance, &instance->io_completion_timer, | 4389 | megasas_start_timer(instance, &instance->io_completion_timer, |
| @@ -4397,6 +4391,12 @@ megasas_resume(struct pci_dev *pdev) | |||
| 4397 | MEGASAS_COMPLETION_TIMER_INTERVAL); | 4391 | MEGASAS_COMPLETION_TIMER_INTERVAL); |
| 4398 | instance->unload = 0; | 4392 | instance->unload = 0; |
| 4399 | 4393 | ||
| 4394 | /* | ||
| 4395 | * Initiate AEN (Asynchronous Event Notification) | ||
| 4396 | */ | ||
| 4397 | if (megasas_start_aen(instance)) | ||
| 4398 | printk(KERN_ERR "megasas: Start AEN failed\n"); | ||
| 4399 | |||
| 4400 | return 0; | 4400 | return 0; |
| 4401 | 4401 | ||
| 4402 | fail_irq: | 4402 | fail_irq: |
| @@ -4527,6 +4527,11 @@ static void megasas_shutdown(struct pci_dev *pdev) | |||
| 4527 | instance->unload = 1; | 4527 | instance->unload = 1; |
| 4528 | megasas_flush_cache(instance); | 4528 | megasas_flush_cache(instance); |
| 4529 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 4529 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
| 4530 | instance->instancet->disable_intr(instance->reg_set); | ||
| 4531 | free_irq(instance->msi_flag ? instance->msixentry.vector : | ||
| 4532 | instance->pdev->irq, instance); | ||
| 4533 | if (instance->msi_flag) | ||
| 4534 | pci_disable_msix(instance->pdev); | ||
| 4530 | } | 4535 | } |
| 4531 | 4536 | ||
| 4532 | /** | 4537 | /** |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 145a8cffb1fa..f13e7abd345a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
| @@ -696,22 +696,6 @@ fail_get_cmd: | |||
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | /* | 698 | /* |
| 699 | * megasas_return_cmd_for_smid - Returns a cmd_fusion for a SMID | ||
| 700 | * @instance: Adapter soft state | ||
| 701 | * | ||
| 702 | */ | ||
| 703 | void | ||
| 704 | megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid) | ||
| 705 | { | ||
| 706 | struct fusion_context *fusion; | ||
| 707 | struct megasas_cmd_fusion *cmd; | ||
| 708 | |||
| 709 | fusion = instance->ctrl_context; | ||
| 710 | cmd = fusion->cmd_list[smid - 1]; | ||
| 711 | megasas_return_cmd_fusion(instance, cmd); | ||
| 712 | } | ||
| 713 | |||
| 714 | /* | ||
| 715 | * megasas_get_ld_map_info - Returns FW's ld_map structure | 699 | * megasas_get_ld_map_info - Returns FW's ld_map structure |
| 716 | * @instance: Adapter soft state | 700 | * @instance: Adapter soft state |
| 717 | * @pend: Pend the command or not | 701 | * @pend: Pend the command or not |
| @@ -1153,7 +1137,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, | |||
| 1153 | u64 start_blk = io_info->pdBlock; | 1137 | u64 start_blk = io_info->pdBlock; |
| 1154 | u8 *cdb = io_request->CDB.CDB32; | 1138 | u8 *cdb = io_request->CDB.CDB32; |
| 1155 | u32 num_blocks = io_info->numBlocks; | 1139 | u32 num_blocks = io_info->numBlocks; |
| 1156 | u8 opcode, flagvals, groupnum, control; | 1140 | u8 opcode = 0, flagvals = 0, groupnum = 0, control = 0; |
| 1157 | 1141 | ||
| 1158 | /* Check if T10 PI (DIF) is enabled for this LD */ | 1142 | /* Check if T10 PI (DIF) is enabled for this LD */ |
| 1159 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); | 1143 | ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); |
| @@ -1235,7 +1219,46 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, | |||
| 1235 | cdb[8] = (u8)(num_blocks & 0xff); | 1219 | cdb[8] = (u8)(num_blocks & 0xff); |
| 1236 | cdb[7] = (u8)((num_blocks >> 8) & 0xff); | 1220 | cdb[7] = (u8)((num_blocks >> 8) & 0xff); |
| 1237 | 1221 | ||
| 1222 | io_request->IoFlags = 10; /* Specify 10-byte cdb */ | ||
| 1238 | cdb_len = 10; | 1223 | cdb_len = 10; |
| 1224 | } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) { | ||
| 1225 | /* Convert to 16 byte CDB for large LBA's */ | ||
| 1226 | switch (cdb_len) { | ||
| 1227 | case 6: | ||
| 1228 | opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16; | ||
| 1229 | control = cdb[5]; | ||
| 1230 | break; | ||
| 1231 | case 10: | ||
| 1232 | opcode = | ||
| 1233 | cdb[0] == READ_10 ? READ_16 : WRITE_16; | ||
| 1234 | flagvals = cdb[1]; | ||
| 1235 | groupnum = cdb[6]; | ||
| 1236 | control = cdb[9]; | ||
| 1237 | break; | ||
| 1238 | case 12: | ||
| 1239 | opcode = | ||
| 1240 | cdb[0] == READ_12 ? READ_16 : WRITE_16; | ||
| 1241 | flagvals = cdb[1]; | ||
| 1242 | groupnum = cdb[10]; | ||
| 1243 | control = cdb[11]; | ||
| 1244 | break; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | memset(cdb, 0, sizeof(io_request->CDB.CDB32)); | ||
| 1248 | |||
| 1249 | cdb[0] = opcode; | ||
| 1250 | cdb[1] = flagvals; | ||
| 1251 | cdb[14] = groupnum; | ||
| 1252 | cdb[15] = control; | ||
| 1253 | |||
| 1254 | /* Transfer length */ | ||
| 1255 | cdb[13] = (u8)(num_blocks & 0xff); | ||
| 1256 | cdb[12] = (u8)((num_blocks >> 8) & 0xff); | ||
| 1257 | cdb[11] = (u8)((num_blocks >> 16) & 0xff); | ||
| 1258 | cdb[10] = (u8)((num_blocks >> 24) & 0xff); | ||
| 1259 | |||
| 1260 | io_request->IoFlags = 16; /* Specify 16-byte cdb */ | ||
| 1261 | cdb_len = 16; | ||
| 1239 | } | 1262 | } |
| 1240 | 1263 | ||
| 1241 | /* Normal case, just load LBA here */ | 1264 | /* Normal case, just load LBA here */ |
| @@ -2026,17 +2049,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2026 | struct fusion_context *fusion; | 2049 | struct fusion_context *fusion; |
| 2027 | struct megasas_cmd *cmd_mfi; | 2050 | struct megasas_cmd *cmd_mfi; |
| 2028 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; | 2051 | union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; |
| 2029 | u32 host_diag, abs_state; | 2052 | u32 host_diag, abs_state, status_reg, reset_adapter; |
| 2030 | 2053 | ||
| 2031 | instance = (struct megasas_instance *)shost->hostdata; | 2054 | instance = (struct megasas_instance *)shost->hostdata; |
| 2032 | fusion = instance->ctrl_context; | 2055 | fusion = instance->ctrl_context; |
| 2033 | 2056 | ||
| 2034 | mutex_lock(&instance->reset_mutex); | ||
| 2035 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | ||
| 2036 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | ||
| 2037 | instance->instancet->disable_intr(instance->reg_set); | ||
| 2038 | msleep(1000); | ||
| 2039 | |||
| 2040 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { | 2057 | if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { |
| 2041 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " | 2058 | printk(KERN_WARNING "megaraid_sas: Hardware critical error, " |
| 2042 | "returning FAILED.\n"); | 2059 | "returning FAILED.\n"); |
| @@ -2044,6 +2061,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2044 | goto out; | 2061 | goto out; |
| 2045 | } | 2062 | } |
| 2046 | 2063 | ||
| 2064 | mutex_lock(&instance->reset_mutex); | ||
| 2065 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | ||
| 2066 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | ||
| 2067 | instance->instancet->disable_intr(instance->reg_set); | ||
| 2068 | msleep(1000); | ||
| 2069 | |||
| 2047 | /* First try waiting for commands to complete */ | 2070 | /* First try waiting for commands to complete */ |
| 2048 | if (megasas_wait_for_outstanding_fusion(instance)) { | 2071 | if (megasas_wait_for_outstanding_fusion(instance)) { |
| 2049 | printk(KERN_WARNING "megaraid_sas: resetting fusion " | 2072 | printk(KERN_WARNING "megaraid_sas: resetting fusion " |
| @@ -2060,7 +2083,12 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2060 | } | 2083 | } |
| 2061 | } | 2084 | } |
| 2062 | 2085 | ||
| 2063 | if (instance->disableOnlineCtrlReset == 1) { | 2086 | status_reg = instance->instancet->read_fw_status_reg( |
| 2087 | instance->reg_set); | ||
| 2088 | abs_state = status_reg & MFI_STATE_MASK; | ||
| 2089 | reset_adapter = status_reg & MFI_RESET_ADAPTER; | ||
| 2090 | if (instance->disableOnlineCtrlReset || | ||
| 2091 | (abs_state == MFI_STATE_FAULT && !reset_adapter)) { | ||
| 2064 | /* Reset not supported, kill adapter */ | 2092 | /* Reset not supported, kill adapter */ |
| 2065 | printk(KERN_WARNING "megaraid_sas: Reset not supported" | 2093 | printk(KERN_WARNING "megaraid_sas: Reset not supported" |
| 2066 | ", killing adapter.\n"); | 2094 | ", killing adapter.\n"); |
| @@ -2089,6 +2117,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2089 | 2117 | ||
| 2090 | /* Check that the diag write enable (DRWE) bit is on */ | 2118 | /* Check that the diag write enable (DRWE) bit is on */ |
| 2091 | host_diag = readl(&instance->reg_set->fusion_host_diag); | 2119 | host_diag = readl(&instance->reg_set->fusion_host_diag); |
| 2120 | retry = 0; | ||
| 2092 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { | 2121 | while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { |
| 2093 | msleep(100); | 2122 | msleep(100); |
| 2094 | host_diag = | 2123 | host_diag = |
| @@ -2126,7 +2155,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2126 | 2155 | ||
| 2127 | abs_state = | 2156 | abs_state = |
| 2128 | instance->instancet->read_fw_status_reg( | 2157 | instance->instancet->read_fw_status_reg( |
| 2129 | instance->reg_set); | 2158 | instance->reg_set) & MFI_STATE_MASK; |
| 2130 | retry = 0; | 2159 | retry = 0; |
| 2131 | 2160 | ||
| 2132 | while ((abs_state <= MFI_STATE_FW_INIT) && | 2161 | while ((abs_state <= MFI_STATE_FW_INIT) && |
| @@ -2134,7 +2163,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
| 2134 | msleep(100); | 2163 | msleep(100); |
| 2135 | abs_state = | 2164 | abs_state = |
| 2136 | instance->instancet->read_fw_status_reg( | 2165 | instance->instancet->read_fw_status_reg( |
| 2137 | instance->reg_set); | 2166 | instance->reg_set) & MFI_STATE_MASK; |
| 2138 | } | 2167 | } |
| 2139 | if (abs_state <= MFI_STATE_FW_INIT) { | 2168 | if (abs_state <= MFI_STATE_FW_INIT) { |
| 2140 | printk(KERN_WARNING "megaraid_sas: firmware " | 2169 | printk(KERN_WARNING "megaraid_sas: firmware " |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 2a3c05f6db8b..dcc289c25459 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
| @@ -69,11 +69,11 @@ | |||
| 69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | 69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" |
| 70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" | 70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" |
| 71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | 71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" |
| 72 | #define MPT2SAS_DRIVER_VERSION "08.100.00.01" | 72 | #define MPT2SAS_DRIVER_VERSION "08.100.00.02" |
| 73 | #define MPT2SAS_MAJOR_VERSION 08 | 73 | #define MPT2SAS_MAJOR_VERSION 08 |
| 74 | #define MPT2SAS_MINOR_VERSION 100 | 74 | #define MPT2SAS_MINOR_VERSION 100 |
| 75 | #define MPT2SAS_BUILD_VERSION 00 | 75 | #define MPT2SAS_BUILD_VERSION 00 |
| 76 | #define MPT2SAS_RELEASE_VERSION 01 | 76 | #define MPT2SAS_RELEASE_VERSION 02 |
| 77 | 77 | ||
| 78 | /* | 78 | /* |
| 79 | * Set MPT2SAS_SG_DEPTH value based on user input. | 79 | * Set MPT2SAS_SG_DEPTH value based on user input. |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index f12e02358d6d..a7dbc6825f5f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -113,6 +113,7 @@ struct sense_info { | |||
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | #define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC) | ||
| 116 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) | 117 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) |
| 117 | 118 | ||
| 118 | /** | 119 | /** |
| @@ -121,6 +122,7 @@ struct sense_info { | |||
| 121 | * @work: work object (ioc->fault_reset_work_q) | 122 | * @work: work object (ioc->fault_reset_work_q) |
| 122 | * @cancel_pending_work: flag set during reset handling | 123 | * @cancel_pending_work: flag set during reset handling |
| 123 | * @ioc: per adapter object | 124 | * @ioc: per adapter object |
| 125 | * @device_handle: device handle | ||
| 124 | * @VF_ID: virtual function id | 126 | * @VF_ID: virtual function id |
| 125 | * @VP_ID: virtual port id | 127 | * @VP_ID: virtual port id |
| 126 | * @ignore: flag meaning this event has been marked to ignore | 128 | * @ignore: flag meaning this event has been marked to ignore |
| @@ -134,6 +136,7 @@ struct fw_event_work { | |||
| 134 | u8 cancel_pending_work; | 136 | u8 cancel_pending_work; |
| 135 | struct delayed_work delayed_work; | 137 | struct delayed_work delayed_work; |
| 136 | struct MPT2SAS_ADAPTER *ioc; | 138 | struct MPT2SAS_ADAPTER *ioc; |
| 139 | u16 device_handle; | ||
| 137 | u8 VF_ID; | 140 | u8 VF_ID; |
| 138 | u8 VP_ID; | 141 | u8 VP_ID; |
| 139 | u8 ignore; | 142 | u8 ignore; |
| @@ -3499,6 +3502,7 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
| 3499 | 3502 | ||
| 3500 | switch (prot_type) { | 3503 | switch (prot_type) { |
| 3501 | case SCSI_PROT_DIF_TYPE1: | 3504 | case SCSI_PROT_DIF_TYPE1: |
| 3505 | case SCSI_PROT_DIF_TYPE2: | ||
| 3502 | 3506 | ||
| 3503 | /* | 3507 | /* |
| 3504 | * enable ref/guard checking | 3508 | * enable ref/guard checking |
| @@ -3511,13 +3515,6 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
| 3511 | cpu_to_be32(scsi_get_lba(scmd)); | 3515 | cpu_to_be32(scsi_get_lba(scmd)); |
| 3512 | break; | 3516 | break; |
| 3513 | 3517 | ||
| 3514 | case SCSI_PROT_DIF_TYPE2: | ||
| 3515 | |||
| 3516 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
| 3517 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | ||
| 3518 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
| 3519 | break; | ||
| 3520 | |||
| 3521 | case SCSI_PROT_DIF_TYPE3: | 3518 | case SCSI_PROT_DIF_TYPE3: |
| 3522 | 3519 | ||
| 3523 | /* | 3520 | /* |
| @@ -4047,17 +4044,75 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4047 | #endif | 4044 | #endif |
| 4048 | 4045 | ||
| 4049 | /** | 4046 | /** |
| 4050 | * _scsih_smart_predicted_fault - illuminate Fault LED | 4047 | * _scsih_turn_on_fault_led - illuminate Fault LED |
| 4051 | * @ioc: per adapter object | 4048 | * @ioc: per adapter object |
| 4052 | * @handle: device handle | 4049 | * @handle: device handle |
| 4050 | * Context: process | ||
| 4053 | * | 4051 | * |
| 4054 | * Return nothing. | 4052 | * Return nothing. |
| 4055 | */ | 4053 | */ |
| 4056 | static void | 4054 | static void |
| 4057 | _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 4055 | _scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) |
| 4058 | { | 4056 | { |
| 4059 | Mpi2SepReply_t mpi_reply; | 4057 | Mpi2SepReply_t mpi_reply; |
| 4060 | Mpi2SepRequest_t mpi_request; | 4058 | Mpi2SepRequest_t mpi_request; |
| 4059 | |||
| 4060 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | ||
| 4061 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
| 4062 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
| 4063 | mpi_request.SlotStatus = | ||
| 4064 | cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); | ||
| 4065 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
| 4066 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; | ||
| 4067 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
| 4068 | &mpi_request)) != 0) { | ||
| 4069 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | ||
| 4070 | __FILE__, __LINE__, __func__); | ||
| 4071 | return; | ||
| 4072 | } | ||
| 4073 | |||
| 4074 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
| 4075 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: " | ||
| 4076 | "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name, | ||
| 4077 | le16_to_cpu(mpi_reply.IOCStatus), | ||
| 4078 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
| 4079 | return; | ||
| 4080 | } | ||
| 4081 | } | ||
| 4082 | |||
| 4083 | /** | ||
| 4084 | * _scsih_send_event_to_turn_on_fault_led - fire delayed event | ||
| 4085 | * @ioc: per adapter object | ||
| 4086 | * @handle: device handle | ||
| 4087 | * Context: interrupt. | ||
| 4088 | * | ||
| 4089 | * Return nothing. | ||
| 4090 | */ | ||
| 4091 | static void | ||
| 4092 | _scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 4093 | { | ||
| 4094 | struct fw_event_work *fw_event; | ||
| 4095 | |||
| 4096 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | ||
| 4097 | if (!fw_event) | ||
| 4098 | return; | ||
| 4099 | fw_event->event = MPT2SAS_TURN_ON_FAULT_LED; | ||
| 4100 | fw_event->device_handle = handle; | ||
| 4101 | fw_event->ioc = ioc; | ||
| 4102 | _scsih_fw_event_add(ioc, fw_event); | ||
| 4103 | } | ||
| 4104 | |||
| 4105 | /** | ||
| 4106 | * _scsih_smart_predicted_fault - process smart errors | ||
| 4107 | * @ioc: per adapter object | ||
| 4108 | * @handle: device handle | ||
| 4109 | * Context: interrupt. | ||
| 4110 | * | ||
| 4111 | * Return nothing. | ||
| 4112 | */ | ||
| 4113 | static void | ||
| 4114 | _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 4115 | { | ||
| 4061 | struct scsi_target *starget; | 4116 | struct scsi_target *starget; |
| 4062 | struct MPT2SAS_TARGET *sas_target_priv_data; | 4117 | struct MPT2SAS_TARGET *sas_target_priv_data; |
| 4063 | Mpi2EventNotificationReply_t *event_reply; | 4118 | Mpi2EventNotificationReply_t *event_reply; |
| @@ -4084,30 +4139,8 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4084 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | 4139 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); |
| 4085 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4140 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4086 | 4141 | ||
| 4087 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) { | 4142 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) |
| 4088 | memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); | 4143 | _scsih_send_event_to_turn_on_fault_led(ioc, handle); |
| 4089 | mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; | ||
| 4090 | mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; | ||
| 4091 | mpi_request.SlotStatus = | ||
| 4092 | cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); | ||
| 4093 | mpi_request.DevHandle = cpu_to_le16(handle); | ||
| 4094 | mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; | ||
| 4095 | if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply, | ||
| 4096 | &mpi_request)) != 0) { | ||
| 4097 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4098 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 4099 | return; | ||
| 4100 | } | ||
| 4101 | |||
| 4102 | if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { | ||
| 4103 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 4104 | "enclosure_processor: ioc_status (0x%04x), " | ||
| 4105 | "loginfo(0x%08x)\n", ioc->name, | ||
| 4106 | le16_to_cpu(mpi_reply.IOCStatus), | ||
| 4107 | le32_to_cpu(mpi_reply.IOCLogInfo))); | ||
| 4108 | return; | ||
| 4109 | } | ||
| 4110 | } | ||
| 4111 | 4144 | ||
| 4112 | /* insert into event log */ | 4145 | /* insert into event log */ |
| 4113 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + | 4146 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + |
| @@ -6753,6 +6786,9 @@ _firmware_event_work(struct work_struct *work) | |||
| 6753 | } | 6786 | } |
| 6754 | 6787 | ||
| 6755 | switch (fw_event->event) { | 6788 | switch (fw_event->event) { |
| 6789 | case MPT2SAS_TURN_ON_FAULT_LED: | ||
| 6790 | _scsih_turn_on_fault_led(ioc, fw_event->device_handle); | ||
| 6791 | break; | ||
| 6756 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | 6792 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: |
| 6757 | _scsih_sas_topology_change_event(ioc, fw_event); | 6793 | _scsih_sas_topology_change_event(ioc, fw_event); |
| 6758 | break; | 6794 | break; |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 58f5be4740e9..de0b1a704fb5 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
| @@ -4698,12 +4698,14 @@ static int __os_scsi_tape_open(struct inode * inode, struct file * filp) | |||
| 4698 | break; | 4698 | break; |
| 4699 | 4699 | ||
| 4700 | if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { | 4700 | if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { |
| 4701 | int j; | ||
| 4702 | |||
| 4701 | STp->pos_unknown = 0; | 4703 | STp->pos_unknown = 0; |
| 4702 | STp->partition = STp->new_partition = 0; | 4704 | STp->partition = STp->new_partition = 0; |
| 4703 | if (STp->can_partitions) | 4705 | if (STp->can_partitions) |
| 4704 | STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ | 4706 | STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ |
| 4705 | for (i=0; i < ST_NBR_PARTITIONS; i++) { | 4707 | for (j = 0; j < ST_NBR_PARTITIONS; j++) { |
| 4706 | STps = &(STp->ps[i]); | 4708 | STps = &(STp->ps[j]); |
| 4707 | STps->rw = ST_IDLE; | 4709 | STps->rw = ST_IDLE; |
| 4708 | STps->eof = ST_NOEOF; | 4710 | STps->eof = ST_NOEOF; |
| 4709 | STps->at_sm = 0; | 4711 | STps->at_sm = 0; |
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile index 0339ff03a535..252523d7847e 100644 --- a/drivers/scsi/qla4xxx/Makefile +++ b/drivers/scsi/qla4xxx/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ | 1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ |
| 2 | ql4_nx.o ql4_nvram.o ql4_dbg.o | 2 | ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o |
| 3 | 3 | ||
| 4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o | 4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o |
| 5 | 5 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c new file mode 100644 index 000000000000..864d018631c0 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_attr.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * QLogic iSCSI HBA Driver | ||
| 3 | * Copyright (c) 2003-2011 QLogic Corporation | ||
| 4 | * | ||
| 5 | * See LICENSE.qla4xxx for copyright and licensing details. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "ql4_def.h" | ||
| 9 | #include "ql4_glbl.h" | ||
| 10 | #include "ql4_dbg.h" | ||
| 11 | |||
| 12 | /* Scsi_Host attributes. */ | ||
| 13 | static ssize_t | ||
| 14 | qla4xxx_fw_version_show(struct device *dev, | ||
| 15 | struct device_attribute *attr, char *buf) | ||
| 16 | { | ||
| 17 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
| 18 | |||
| 19 | if (is_qla8022(ha)) | ||
| 20 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n", | ||
| 21 | ha->firmware_version[0], | ||
| 22 | ha->firmware_version[1], | ||
| 23 | ha->patch_number, ha->build_number); | ||
| 24 | else | ||
| 25 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", | ||
| 26 | ha->firmware_version[0], | ||
| 27 | ha->firmware_version[1], | ||
| 28 | ha->patch_number, ha->build_number); | ||
| 29 | } | ||
| 30 | |||
| 31 | static ssize_t | ||
| 32 | qla4xxx_serial_num_show(struct device *dev, struct device_attribute *attr, | ||
| 33 | char *buf) | ||
| 34 | { | ||
| 35 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
| 36 | return snprintf(buf, PAGE_SIZE, "%s\n", ha->serial_number); | ||
| 37 | } | ||
| 38 | |||
| 39 | static ssize_t | ||
| 40 | qla4xxx_iscsi_version_show(struct device *dev, struct device_attribute *attr, | ||
| 41 | char *buf) | ||
| 42 | { | ||
| 43 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
| 44 | return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->iscsi_major, | ||
| 45 | ha->iscsi_minor); | ||
| 46 | } | ||
| 47 | |||
| 48 | static ssize_t | ||
| 49 | qla4xxx_optrom_version_show(struct device *dev, struct device_attribute *attr, | ||
| 50 | char *buf) | ||
| 51 | { | ||
| 52 | struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev)); | ||
| 53 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d.%02d\n", | ||
| 54 | ha->bootload_major, ha->bootload_minor, | ||
| 55 | ha->bootload_patch, ha->bootload_build); | ||
| 56 | } | ||
| 57 | |||
| 58 | static DEVICE_ATTR(fw_version, S_IRUGO, qla4xxx_fw_version_show, NULL); | ||
| 59 | static DEVICE_ATTR(serial_num, S_IRUGO, qla4xxx_serial_num_show, NULL); | ||
| 60 | static DEVICE_ATTR(iscsi_version, S_IRUGO, qla4xxx_iscsi_version_show, NULL); | ||
| 61 | static DEVICE_ATTR(optrom_version, S_IRUGO, qla4xxx_optrom_version_show, NULL); | ||
| 62 | |||
| 63 | struct device_attribute *qla4xxx_host_attrs[] = { | ||
| 64 | &dev_attr_fw_version, | ||
| 65 | &dev_attr_serial_num, | ||
| 66 | &dev_attr_iscsi_version, | ||
| 67 | &dev_attr_optrom_version, | ||
| 68 | NULL, | ||
| 69 | }; | ||
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 4757878d59dd..473c5c872b39 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
| @@ -115,7 +115,7 @@ | |||
| 115 | #define INVALID_ENTRY 0xFFFF | 115 | #define INVALID_ENTRY 0xFFFF |
| 116 | #define MAX_CMDS_TO_RISC 1024 | 116 | #define MAX_CMDS_TO_RISC 1024 |
| 117 | #define MAX_SRBS MAX_CMDS_TO_RISC | 117 | #define MAX_SRBS MAX_CMDS_TO_RISC |
| 118 | #define MBOX_AEN_REG_COUNT 5 | 118 | #define MBOX_AEN_REG_COUNT 8 |
| 119 | #define MAX_INIT_RETRIES 5 | 119 | #define MAX_INIT_RETRIES 5 |
| 120 | 120 | ||
| 121 | /* | 121 | /* |
| @@ -368,7 +368,6 @@ struct scsi_qla_host { | |||
| 368 | #define AF_INIT_DONE 1 /* 0x00000002 */ | 368 | #define AF_INIT_DONE 1 /* 0x00000002 */ |
| 369 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ | 369 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ |
| 370 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ | 370 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ |
| 371 | #define AF_DPC_SCHEDULED 5 /* 0x00000020 */ | ||
| 372 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ | 371 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ |
| 373 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 372 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
| 374 | #define AF_LINK_UP 8 /* 0x00000100 */ | 373 | #define AF_LINK_UP 8 /* 0x00000100 */ |
| @@ -584,6 +583,14 @@ struct scsi_qla_host { | |||
| 584 | uint32_t nx_reset_timeout; | 583 | uint32_t nx_reset_timeout; |
| 585 | 584 | ||
| 586 | struct completion mbx_intr_comp; | 585 | struct completion mbx_intr_comp; |
| 586 | |||
| 587 | /* --- From About Firmware --- */ | ||
| 588 | uint16_t iscsi_major; | ||
| 589 | uint16_t iscsi_minor; | ||
| 590 | uint16_t bootload_major; | ||
| 591 | uint16_t bootload_minor; | ||
| 592 | uint16_t bootload_patch; | ||
| 593 | uint16_t bootload_build; | ||
| 587 | }; | 594 | }; |
| 588 | 595 | ||
| 589 | static inline int is_ipv4_enabled(struct scsi_qla_host *ha) | 596 | static inline int is_ipv4_enabled(struct scsi_qla_host *ha) |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 31e2bf97198c..01082aa77098 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
| @@ -690,6 +690,29 @@ struct mbx_sys_info { | |||
| 690 | uint8_t reserved[12]; /* 34-3f */ | 690 | uint8_t reserved[12]; /* 34-3f */ |
| 691 | }; | 691 | }; |
| 692 | 692 | ||
| 693 | struct about_fw_info { | ||
| 694 | uint16_t fw_major; /* 00 - 01 */ | ||
| 695 | uint16_t fw_minor; /* 02 - 03 */ | ||
| 696 | uint16_t fw_patch; /* 04 - 05 */ | ||
| 697 | uint16_t fw_build; /* 06 - 07 */ | ||
| 698 | uint8_t fw_build_date[16]; /* 08 - 17 ASCII String */ | ||
| 699 | uint8_t fw_build_time[16]; /* 18 - 27 ASCII String */ | ||
| 700 | uint8_t fw_build_user[16]; /* 28 - 37 ASCII String */ | ||
| 701 | uint16_t fw_load_source; /* 38 - 39 */ | ||
| 702 | /* 1 = Flash Primary, | ||
| 703 | 2 = Flash Secondary, | ||
| 704 | 3 = Host Download | ||
| 705 | */ | ||
| 706 | uint8_t reserved1[6]; /* 3A - 3F */ | ||
| 707 | uint16_t iscsi_major; /* 40 - 41 */ | ||
| 708 | uint16_t iscsi_minor; /* 42 - 43 */ | ||
| 709 | uint16_t bootload_major; /* 44 - 45 */ | ||
| 710 | uint16_t bootload_minor; /* 46 - 47 */ | ||
| 711 | uint16_t bootload_patch; /* 48 - 49 */ | ||
| 712 | uint16_t bootload_build; /* 4A - 4B */ | ||
| 713 | uint8_t reserved2[180]; /* 4C - FF */ | ||
| 714 | }; | ||
| 715 | |||
| 693 | struct crash_record { | 716 | struct crash_record { |
| 694 | uint16_t fw_major_version; /* 00 - 01 */ | 717 | uint16_t fw_major_version; /* 00 - 01 */ |
| 695 | uint16_t fw_minor_version; /* 02 - 03 */ | 718 | uint16_t fw_minor_version; /* 02 - 03 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index cc53e3fbd78c..a53a256c1f8d 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
| @@ -61,7 +61,7 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); | |||
| 61 | int qla4xxx_add_sess(struct ddb_entry *); | 61 | int qla4xxx_add_sess(struct ddb_entry *); |
| 62 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); | 62 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); |
| 63 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); | 63 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); |
| 64 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha); | 64 | int qla4xxx_about_firmware(struct scsi_qla_host *ha); |
| 65 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, | 65 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, |
| 66 | uint32_t intr_status); | 66 | uint32_t intr_status); |
| 67 | int qla4xxx_init_rings(struct scsi_qla_host *ha); | 67 | int qla4xxx_init_rings(struct scsi_qla_host *ha); |
| @@ -139,4 +139,5 @@ extern int ql4xextended_error_logging; | |||
| 139 | extern int ql4xdontresethba; | 139 | extern int ql4xdontresethba; |
| 140 | extern int ql4xenablemsix; | 140 | extern int ql4xenablemsix; |
| 141 | 141 | ||
| 142 | extern struct device_attribute *qla4xxx_host_attrs[]; | ||
| 142 | #endif /* _QLA4x_GBL_H */ | 143 | #endif /* _QLA4x_GBL_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 48e2241ddaf4..42ed5db2d530 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
| @@ -1275,7 +1275,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
| 1275 | if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) | 1275 | if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) |
| 1276 | goto exit_init_hba; | 1276 | goto exit_init_hba; |
| 1277 | 1277 | ||
| 1278 | if (qla4xxx_get_fw_version(ha) == QLA_ERROR) | 1278 | if (qla4xxx_about_firmware(ha) == QLA_ERROR) |
| 1279 | goto exit_init_hba; | 1279 | goto exit_init_hba; |
| 1280 | 1280 | ||
| 1281 | if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) | 1281 | if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 2f40ac761cd4..0e72921c752d 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
| @@ -25,9 +25,14 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, | |||
| 25 | 25 | ||
| 26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); |
| 27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); | 27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); |
| 28 | if (sense_len == 0) | 28 | if (sense_len == 0) { |
| 29 | DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: %s:" | ||
| 30 | " sense len 0\n", ha->host_no, | ||
| 31 | cmd->device->channel, cmd->device->id, | ||
| 32 | cmd->device->lun, __func__)); | ||
| 33 | ha->status_srb = NULL; | ||
| 29 | return; | 34 | return; |
| 30 | 35 | } | |
| 31 | /* Save total available sense length, | 36 | /* Save total available sense length, |
| 32 | * not to exceed cmd's sense buffer size */ | 37 | * not to exceed cmd's sense buffer size */ |
| 33 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); | 38 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); |
| @@ -541,6 +546,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
| 541 | case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED: /* Connection mode */ | 546 | case MBOX_ASTS_UNSOLICITED_PDU_RECEIVED: /* Connection mode */ |
| 542 | case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR: | 547 | case MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR: |
| 543 | case MBOX_ASTS_SUBNET_STATE_CHANGE: | 548 | case MBOX_ASTS_SUBNET_STATE_CHANGE: |
| 549 | case MBOX_ASTS_DUPLICATE_IP: | ||
| 544 | /* No action */ | 550 | /* No action */ |
| 545 | DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no, | 551 | DEBUG2(printk("scsi%ld: AEN %04x\n", ha->host_no, |
| 546 | mbox_status)); | 552 | mbox_status)); |
| @@ -593,11 +599,13 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
| 593 | mbox_sts[i]; | 599 | mbox_sts[i]; |
| 594 | 600 | ||
| 595 | /* print debug message */ | 601 | /* print debug message */ |
| 596 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued" | 602 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued " |
| 597 | " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", | 603 | "mb1:0x%x mb2:0x%x mb3:0x%x " |
| 598 | ha->host_no, ha->aen_in, mbox_sts[0], | 604 | "mb4:0x%x mb5:0x%x\n", |
| 599 | mbox_sts[1], mbox_sts[2], mbox_sts[3], | 605 | ha->host_no, ha->aen_in, |
| 600 | mbox_sts[4])); | 606 | mbox_sts[0], mbox_sts[1], |
| 607 | mbox_sts[2], mbox_sts[3], | ||
| 608 | mbox_sts[4], mbox_sts[5])); | ||
| 601 | 609 | ||
| 602 | /* advance pointer */ | 610 | /* advance pointer */ |
| 603 | ha->aen_in++; | 611 | ha->aen_in++; |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index d78b58dc5011..fce8289e9752 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
| @@ -86,22 +86,8 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
| 86 | msleep(10); | 86 | msleep(10); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /* To prevent overwriting mailbox registers for a command that has | ||
| 90 | * not yet been serviced, check to see if an active command | ||
| 91 | * (AEN, IOCB, etc.) is interrupting, then service it. | ||
| 92 | * ----------------------------------------------------------------- | ||
| 93 | */ | ||
| 94 | spin_lock_irqsave(&ha->hardware_lock, flags); | 89 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 95 | 90 | ||
| 96 | if (!is_qla8022(ha)) { | ||
| 97 | intr_status = readl(&ha->reg->ctrl_status); | ||
| 98 | if (intr_status & CSR_SCSI_PROCESSOR_INTR) { | ||
| 99 | /* Service existing interrupt */ | ||
| 100 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
| 101 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | ha->mbox_status_count = outCount; | 91 | ha->mbox_status_count = outCount; |
| 106 | for (i = 0; i < outCount; i++) | 92 | for (i = 0; i < outCount; i++) |
| 107 | ha->mbox_status[i] = 0; | 93 | ha->mbox_status[i] = 0; |
| @@ -1057,38 +1043,65 @@ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, | |||
| 1057 | } | 1043 | } |
| 1058 | 1044 | ||
| 1059 | /** | 1045 | /** |
| 1060 | * qla4xxx_get_fw_version - gets firmware version | 1046 | * qla4xxx_about_firmware - gets FW, iscsi draft and boot loader version |
| 1061 | * @ha: Pointer to host adapter structure. | 1047 | * @ha: Pointer to host adapter structure. |
| 1062 | * | 1048 | * |
| 1063 | * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may | 1049 | * Retrieves the FW version, iSCSI draft version & bootloader version of HBA. |
| 1064 | * hold an address for data. Make sure that we write 0 to those mailboxes, | 1050 | * Mailboxes 2 & 3 may hold an address for data. Make sure that we write 0 to |
| 1065 | * if unused. | 1051 | * those mailboxes, if unused. |
| 1066 | **/ | 1052 | **/ |
| 1067 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha) | 1053 | int qla4xxx_about_firmware(struct scsi_qla_host *ha) |
| 1068 | { | 1054 | { |
| 1055 | struct about_fw_info *about_fw = NULL; | ||
| 1056 | dma_addr_t about_fw_dma; | ||
| 1069 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 1057 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
| 1070 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 1058 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
| 1059 | int status = QLA_ERROR; | ||
| 1060 | |||
| 1061 | about_fw = dma_alloc_coherent(&ha->pdev->dev, | ||
| 1062 | sizeof(struct about_fw_info), | ||
| 1063 | &about_fw_dma, GFP_KERNEL); | ||
| 1064 | if (!about_fw) { | ||
| 1065 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory " | ||
| 1066 | "for about_fw\n", __func__)); | ||
| 1067 | return status; | ||
| 1068 | } | ||
| 1071 | 1069 | ||
| 1072 | /* Get firmware version. */ | 1070 | memset(about_fw, 0, sizeof(struct about_fw_info)); |
| 1073 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | 1071 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); |
| 1074 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | 1072 | memset(&mbox_sts, 0, sizeof(mbox_sts)); |
| 1075 | 1073 | ||
| 1076 | mbox_cmd[0] = MBOX_CMD_ABOUT_FW; | 1074 | mbox_cmd[0] = MBOX_CMD_ABOUT_FW; |
| 1077 | 1075 | mbox_cmd[2] = LSDW(about_fw_dma); | |
| 1078 | if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != | 1076 | mbox_cmd[3] = MSDW(about_fw_dma); |
| 1079 | QLA_SUCCESS) { | 1077 | mbox_cmd[4] = sizeof(struct about_fw_info); |
| 1080 | DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ " | 1078 | |
| 1081 | "status %04X\n", ha->host_no, __func__, mbox_sts[0])); | 1079 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, |
| 1082 | return QLA_ERROR; | 1080 | &mbox_cmd[0], &mbox_sts[0]); |
| 1081 | if (status != QLA_SUCCESS) { | ||
| 1082 | DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: MBOX_CMD_ABOUT_FW " | ||
| 1083 | "failed w/ status %04X\n", __func__, | ||
| 1084 | mbox_sts[0])); | ||
| 1085 | goto exit_about_fw; | ||
| 1083 | } | 1086 | } |
| 1084 | 1087 | ||
| 1085 | /* Save firmware version information. */ | 1088 | /* Save version information. */ |
| 1086 | ha->firmware_version[0] = mbox_sts[1]; | 1089 | ha->firmware_version[0] = le16_to_cpu(about_fw->fw_major); |
| 1087 | ha->firmware_version[1] = mbox_sts[2]; | 1090 | ha->firmware_version[1] = le16_to_cpu(about_fw->fw_minor); |
| 1088 | ha->patch_number = mbox_sts[3]; | 1091 | ha->patch_number = le16_to_cpu(about_fw->fw_patch); |
| 1089 | ha->build_number = mbox_sts[4]; | 1092 | ha->build_number = le16_to_cpu(about_fw->fw_build); |
| 1093 | ha->iscsi_major = le16_to_cpu(about_fw->iscsi_major); | ||
| 1094 | ha->iscsi_minor = le16_to_cpu(about_fw->iscsi_minor); | ||
| 1095 | ha->bootload_major = le16_to_cpu(about_fw->bootload_major); | ||
| 1096 | ha->bootload_minor = le16_to_cpu(about_fw->bootload_minor); | ||
| 1097 | ha->bootload_patch = le16_to_cpu(about_fw->bootload_patch); | ||
| 1098 | ha->bootload_build = le16_to_cpu(about_fw->bootload_build); | ||
| 1099 | status = QLA_SUCCESS; | ||
| 1090 | 1100 | ||
| 1091 | return QLA_SUCCESS; | 1101 | exit_about_fw: |
| 1102 | dma_free_coherent(&ha->pdev->dev, sizeof(struct about_fw_info), | ||
| 1103 | about_fw, about_fw_dma); | ||
| 1104 | return status; | ||
| 1092 | } | 1105 | } |
| 1093 | 1106 | ||
| 1094 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, | 1107 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 03e522b2fe0b..fdfe27b38698 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
| @@ -964,12 +964,26 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
| 964 | /* Halt all the indiviual PEGs and other blocks of the ISP */ | 964 | /* Halt all the indiviual PEGs and other blocks of the ISP */ |
| 965 | qla4_8xxx_rom_lock(ha); | 965 | qla4_8xxx_rom_lock(ha); |
| 966 | 966 | ||
| 967 | /* mask all niu interrupts */ | 967 | /* disable all I2Q */ |
| 968 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x10, 0x0); | ||
| 969 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x14, 0x0); | ||
| 970 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x18, 0x0); | ||
| 971 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x1c, 0x0); | ||
| 972 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x20, 0x0); | ||
| 973 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_I2Q + 0x24, 0x0); | ||
| 974 | |||
| 975 | /* disable all niu interrupts */ | ||
| 968 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); | 976 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); |
| 969 | /* disable xge rx/tx */ | 977 | /* disable xge rx/tx */ |
| 970 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); | 978 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); |
| 971 | /* disable xg1 rx/tx */ | 979 | /* disable xg1 rx/tx */ |
| 972 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); | 980 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); |
| 981 | /* disable sideband mac */ | ||
| 982 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x90000, 0x00); | ||
| 983 | /* disable ap0 mac */ | ||
| 984 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0xa0000, 0x00); | ||
| 985 | /* disable ap1 mac */ | ||
| 986 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0xb0000, 0x00); | ||
| 973 | 987 | ||
| 974 | /* halt sre */ | 988 | /* halt sre */ |
| 975 | val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); | 989 | val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); |
| @@ -984,6 +998,7 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
| 984 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); | 998 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); |
| 985 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); | 999 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); |
| 986 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); | 1000 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); |
| 1001 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x200, 0x0); | ||
| 987 | 1002 | ||
| 988 | /* halt pegs */ | 1003 | /* halt pegs */ |
| 989 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); | 1004 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); |
| @@ -991,9 +1006,9 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | |||
| 991 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); | 1006 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); |
| 992 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); | 1007 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); |
| 993 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); | 1008 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); |
| 1009 | msleep(5); | ||
| 994 | 1010 | ||
| 995 | /* big hammer */ | 1011 | /* big hammer */ |
| 996 | msleep(1000); | ||
| 997 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) | 1012 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
| 998 | /* don't reset CAM block on reset */ | 1013 | /* don't reset CAM block on reset */ |
| 999 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); | 1014 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c22f2a764d9d..f2364ec59f03 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
| @@ -124,6 +124,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
| 124 | .sg_tablesize = SG_ALL, | 124 | .sg_tablesize = SG_ALL, |
| 125 | 125 | ||
| 126 | .max_sectors = 0xFFFF, | 126 | .max_sectors = 0xFFFF, |
| 127 | .shost_attrs = qla4xxx_host_attrs, | ||
| 127 | }; | 128 | }; |
| 128 | 129 | ||
| 129 | static struct iscsi_transport qla4xxx_iscsi_transport = { | 130 | static struct iscsi_transport qla4xxx_iscsi_transport = { |
| @@ -412,8 +413,7 @@ void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) | |||
| 412 | 413 | ||
| 413 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | 414 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, |
| 414 | struct ddb_entry *ddb_entry, | 415 | struct ddb_entry *ddb_entry, |
| 415 | struct scsi_cmnd *cmd, | 416 | struct scsi_cmnd *cmd) |
| 416 | void (*done)(struct scsi_cmnd *)) | ||
| 417 | { | 417 | { |
| 418 | struct srb *srb; | 418 | struct srb *srb; |
| 419 | 419 | ||
| @@ -427,7 +427,6 @@ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | |||
| 427 | srb->cmd = cmd; | 427 | srb->cmd = cmd; |
| 428 | srb->flags = 0; | 428 | srb->flags = 0; |
| 429 | CMD_SP(cmd) = (void *)srb; | 429 | CMD_SP(cmd) = (void *)srb; |
| 430 | cmd->scsi_done = done; | ||
| 431 | 430 | ||
| 432 | return srb; | 431 | return srb; |
| 433 | } | 432 | } |
| @@ -458,9 +457,8 @@ void qla4xxx_srb_compl(struct kref *ref) | |||
| 458 | 457 | ||
| 459 | /** | 458 | /** |
| 460 | * qla4xxx_queuecommand - scsi layer issues scsi command to driver. | 459 | * qla4xxx_queuecommand - scsi layer issues scsi command to driver. |
| 460 | * @host: scsi host | ||
| 461 | * @cmd: Pointer to Linux's SCSI command structure | 461 | * @cmd: Pointer to Linux's SCSI command structure |
| 462 | * @done_fn: Function that the driver calls to notify the SCSI mid-layer | ||
| 463 | * that the command has been processed. | ||
| 464 | * | 462 | * |
| 465 | * Remarks: | 463 | * Remarks: |
| 466 | * This routine is invoked by Linux to send a SCSI command to the driver. | 464 | * This routine is invoked by Linux to send a SCSI command to the driver. |
| @@ -470,10 +468,9 @@ void qla4xxx_srb_compl(struct kref *ref) | |||
| 470 | * completion handling). Unfortunely, it sometimes calls the scheduler | 468 | * completion handling). Unfortunely, it sometimes calls the scheduler |
| 471 | * in interrupt context which is a big NO! NO!. | 469 | * in interrupt context which is a big NO! NO!. |
| 472 | **/ | 470 | **/ |
| 473 | static int qla4xxx_queuecommand_lck(struct scsi_cmnd *cmd, | 471 | static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) |
| 474 | void (*done)(struct scsi_cmnd *)) | ||
| 475 | { | 472 | { |
| 476 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 473 | struct scsi_qla_host *ha = to_qla_host(host); |
| 477 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 474 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
| 478 | struct iscsi_cls_session *sess = ddb_entry->sess; | 475 | struct iscsi_cls_session *sess = ddb_entry->sess; |
| 479 | struct srb *srb; | 476 | struct srb *srb; |
| @@ -515,37 +512,29 @@ static int qla4xxx_queuecommand_lck(struct scsi_cmnd *cmd, | |||
| 515 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) | 512 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) |
| 516 | goto qc_host_busy; | 513 | goto qc_host_busy; |
| 517 | 514 | ||
| 518 | spin_unlock_irq(ha->host->host_lock); | 515 | srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd); |
| 519 | |||
| 520 | srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done); | ||
| 521 | if (!srb) | 516 | if (!srb) |
| 522 | goto qc_host_busy_lock; | 517 | goto qc_host_busy; |
| 523 | 518 | ||
| 524 | rval = qla4xxx_send_command_to_isp(ha, srb); | 519 | rval = qla4xxx_send_command_to_isp(ha, srb); |
| 525 | if (rval != QLA_SUCCESS) | 520 | if (rval != QLA_SUCCESS) |
| 526 | goto qc_host_busy_free_sp; | 521 | goto qc_host_busy_free_sp; |
| 527 | 522 | ||
| 528 | spin_lock_irq(ha->host->host_lock); | ||
| 529 | return 0; | 523 | return 0; |
| 530 | 524 | ||
| 531 | qc_host_busy_free_sp: | 525 | qc_host_busy_free_sp: |
| 532 | qla4xxx_srb_free_dma(ha, srb); | 526 | qla4xxx_srb_free_dma(ha, srb); |
| 533 | mempool_free(srb, ha->srb_mempool); | 527 | mempool_free(srb, ha->srb_mempool); |
| 534 | 528 | ||
| 535 | qc_host_busy_lock: | ||
| 536 | spin_lock_irq(ha->host->host_lock); | ||
| 537 | |||
| 538 | qc_host_busy: | 529 | qc_host_busy: |
| 539 | return SCSI_MLQUEUE_HOST_BUSY; | 530 | return SCSI_MLQUEUE_HOST_BUSY; |
| 540 | 531 | ||
| 541 | qc_fail_command: | 532 | qc_fail_command: |
| 542 | done(cmd); | 533 | cmd->scsi_done(cmd); |
| 543 | 534 | ||
| 544 | return 0; | 535 | return 0; |
| 545 | } | 536 | } |
| 546 | 537 | ||
| 547 | static DEF_SCSI_QCMD(qla4xxx_queuecommand) | ||
| 548 | |||
| 549 | /** | 538 | /** |
| 550 | * qla4xxx_mem_free - frees memory allocated to adapter | 539 | * qla4xxx_mem_free - frees memory allocated to adapter |
| 551 | * @ha: Pointer to host adapter structure. | 540 | * @ha: Pointer to host adapter structure. |
| @@ -679,7 +668,27 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
| 679 | if (ha->seconds_since_last_heartbeat == 2) { | 668 | if (ha->seconds_since_last_heartbeat == 2) { |
| 680 | ha->seconds_since_last_heartbeat = 0; | 669 | ha->seconds_since_last_heartbeat = 0; |
| 681 | halt_status = qla4_8xxx_rd_32(ha, | 670 | halt_status = qla4_8xxx_rd_32(ha, |
| 682 | QLA82XX_PEG_HALT_STATUS1); | 671 | QLA82XX_PEG_HALT_STATUS1); |
| 672 | |||
| 673 | ql4_printk(KERN_INFO, ha, | ||
| 674 | "scsi(%ld): %s, Dumping hw/fw registers:\n " | ||
| 675 | " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2:" | ||
| 676 | " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:" | ||
| 677 | " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:" | ||
| 678 | " 0x%x,\n PEG_NET_4_PC: 0x%x\n", | ||
| 679 | ha->host_no, __func__, halt_status, | ||
| 680 | qla4_8xxx_rd_32(ha, | ||
| 681 | QLA82XX_PEG_HALT_STATUS2), | ||
| 682 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + | ||
| 683 | 0x3c), | ||
| 684 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 + | ||
| 685 | 0x3c), | ||
| 686 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 + | ||
| 687 | 0x3c), | ||
| 688 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 + | ||
| 689 | 0x3c), | ||
| 690 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + | ||
| 691 | 0x3c)); | ||
| 683 | 692 | ||
| 684 | /* Since we cannot change dev_state in interrupt | 693 | /* Since we cannot change dev_state in interrupt |
| 685 | * context, set appropriate DPC flag then wakeup | 694 | * context, set appropriate DPC flag then wakeup |
| @@ -715,7 +724,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
| 715 | /* don't poll if reset is going on */ | 724 | /* don't poll if reset is going on */ |
| 716 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | 725 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || |
| 717 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 726 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
| 718 | test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) { | 727 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { |
| 719 | if (dev_state == QLA82XX_DEV_NEED_RESET && | 728 | if (dev_state == QLA82XX_DEV_NEED_RESET && |
| 720 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | 729 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
| 721 | if (!ql4xdontresethba) { | 730 | if (!ql4xdontresethba) { |
| @@ -839,7 +848,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
| 839 | } | 848 | } |
| 840 | 849 | ||
| 841 | /* Wakeup the dpc routine for this adapter, if needed. */ | 850 | /* Wakeup the dpc routine for this adapter, if needed. */ |
| 842 | if ((start_dpc || | 851 | if (start_dpc || |
| 843 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 852 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
| 844 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || | 853 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || |
| 845 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || | 854 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || |
| @@ -849,9 +858,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
| 849 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || | 858 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || |
| 850 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | 859 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || |
| 851 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | 860 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || |
| 852 | test_bit(DPC_AEN, &ha->dpc_flags)) && | 861 | test_bit(DPC_AEN, &ha->dpc_flags)) { |
| 853 | !test_bit(AF_DPC_SCHEDULED, &ha->flags) && | ||
| 854 | ha->dpc_thread) { | ||
| 855 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" | 862 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" |
| 856 | " - dpc flags = 0x%lx\n", | 863 | " - dpc flags = 0x%lx\n", |
| 857 | ha->host_no, __func__, ha->dpc_flags)); | 864 | ha->host_no, __func__, ha->dpc_flags)); |
| @@ -1241,11 +1248,8 @@ static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) | |||
| 1241 | 1248 | ||
| 1242 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | 1249 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) |
| 1243 | { | 1250 | { |
| 1244 | if (ha->dpc_thread && | 1251 | if (ha->dpc_thread) |
| 1245 | !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { | ||
| 1246 | set_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
| 1247 | queue_work(ha->dpc_thread, &ha->dpc_work); | 1252 | queue_work(ha->dpc_thread, &ha->dpc_work); |
| 1248 | } | ||
| 1249 | } | 1253 | } |
| 1250 | 1254 | ||
| 1251 | /** | 1255 | /** |
| @@ -1272,12 +1276,12 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
| 1272 | 1276 | ||
| 1273 | /* Initialization not yet finished. Don't do anything yet. */ | 1277 | /* Initialization not yet finished. Don't do anything yet. */ |
| 1274 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1278 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
| 1275 | goto do_dpc_exit; | 1279 | return; |
| 1276 | 1280 | ||
| 1277 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { | 1281 | if (test_bit(AF_EEH_BUSY, &ha->flags)) { |
| 1278 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", | 1282 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", |
| 1279 | ha->host_no, __func__, ha->flags)); | 1283 | ha->host_no, __func__, ha->flags)); |
| 1280 | goto do_dpc_exit; | 1284 | return; |
| 1281 | } | 1285 | } |
| 1282 | 1286 | ||
| 1283 | if (is_qla8022(ha)) { | 1287 | if (is_qla8022(ha)) { |
| @@ -1384,8 +1388,6 @@ dpc_post_reset_ha: | |||
| 1384 | } | 1388 | } |
| 1385 | } | 1389 | } |
| 1386 | 1390 | ||
| 1387 | do_dpc_exit: | ||
| 1388 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
| 1389 | } | 1391 | } |
| 1390 | 1392 | ||
| 1391 | /** | 1393 | /** |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 603155769407..610492877253 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
| @@ -5,4 +5,4 @@ | |||
| 5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k6" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k7" |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index abea2cf05c2e..a4b9cdbaaa0b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -50,6 +50,8 @@ | |||
| 50 | #define BUS_RESET_SETTLE_TIME (10) | 50 | #define BUS_RESET_SETTLE_TIME (10) |
| 51 | #define HOST_RESET_SETTLE_TIME (10) | 51 | #define HOST_RESET_SETTLE_TIME (10) |
| 52 | 52 | ||
| 53 | static int scsi_eh_try_stu(struct scsi_cmnd *scmd); | ||
| 54 | |||
| 53 | /* called with shost->host_lock held */ | 55 | /* called with shost->host_lock held */ |
| 54 | void scsi_eh_wakeup(struct Scsi_Host *shost) | 56 | void scsi_eh_wakeup(struct Scsi_Host *shost) |
| 55 | { | 57 | { |
| @@ -947,6 +949,48 @@ retry_tur: | |||
| 947 | } | 949 | } |
| 948 | 950 | ||
| 949 | /** | 951 | /** |
| 952 | * scsi_eh_test_devices - check if devices are responding from error recovery. | ||
| 953 | * @cmd_list: scsi commands in error recovery. | ||
| 954 | * @work_q: queue for commands which still need more error recovery | ||
| 955 | * @done_q: queue for commands which are finished | ||
| 956 | * @try_stu: boolean on if a STU command should be tried in addition to TUR. | ||
| 957 | * | ||
| 958 | * Decription: | ||
| 959 | * Tests if devices are in a working state. Commands to devices now in | ||
| 960 | * a working state are sent to the done_q while commands to devices which | ||
| 961 | * are still failing to respond are returned to the work_q for more | ||
| 962 | * processing. | ||
| 963 | **/ | ||
| 964 | static int scsi_eh_test_devices(struct list_head *cmd_list, | ||
| 965 | struct list_head *work_q, | ||
| 966 | struct list_head *done_q, int try_stu) | ||
| 967 | { | ||
| 968 | struct scsi_cmnd *scmd, *next; | ||
| 969 | struct scsi_device *sdev; | ||
| 970 | int finish_cmds; | ||
| 971 | |||
| 972 | while (!list_empty(cmd_list)) { | ||
| 973 | scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); | ||
| 974 | sdev = scmd->device; | ||
| 975 | |||
| 976 | finish_cmds = !scsi_device_online(scmd->device) || | ||
| 977 | (try_stu && !scsi_eh_try_stu(scmd) && | ||
| 978 | !scsi_eh_tur(scmd)) || | ||
| 979 | !scsi_eh_tur(scmd); | ||
| 980 | |||
| 981 | list_for_each_entry_safe(scmd, next, cmd_list, eh_entry) | ||
| 982 | if (scmd->device == sdev) { | ||
| 983 | if (finish_cmds) | ||
| 984 | scsi_eh_finish_cmd(scmd, done_q); | ||
| 985 | else | ||
| 986 | list_move_tail(&scmd->eh_entry, work_q); | ||
| 987 | } | ||
| 988 | } | ||
| 989 | return list_empty(work_q); | ||
| 990 | } | ||
| 991 | |||
| 992 | |||
| 993 | /** | ||
| 950 | * scsi_eh_abort_cmds - abort pending commands. | 994 | * scsi_eh_abort_cmds - abort pending commands. |
| 951 | * @work_q: &list_head for pending commands. | 995 | * @work_q: &list_head for pending commands. |
| 952 | * @done_q: &list_head for processed commands. | 996 | * @done_q: &list_head for processed commands. |
| @@ -962,6 +1006,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
| 962 | struct list_head *done_q) | 1006 | struct list_head *done_q) |
| 963 | { | 1007 | { |
| 964 | struct scsi_cmnd *scmd, *next; | 1008 | struct scsi_cmnd *scmd, *next; |
| 1009 | LIST_HEAD(check_list); | ||
| 965 | int rtn; | 1010 | int rtn; |
| 966 | 1011 | ||
| 967 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1012 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
| @@ -973,11 +1018,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
| 973 | rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); | 1018 | rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); |
| 974 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1019 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { |
| 975 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; | 1020 | scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; |
| 976 | if (!scsi_device_online(scmd->device) || | 1021 | if (rtn == FAST_IO_FAIL) |
| 977 | rtn == FAST_IO_FAIL || | ||
| 978 | !scsi_eh_tur(scmd)) { | ||
| 979 | scsi_eh_finish_cmd(scmd, done_q); | 1022 | scsi_eh_finish_cmd(scmd, done_q); |
| 980 | } | 1023 | else |
| 1024 | list_move_tail(&scmd->eh_entry, &check_list); | ||
| 981 | } else | 1025 | } else |
| 982 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" | 1026 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" |
| 983 | " cmd failed:" | 1027 | " cmd failed:" |
| @@ -986,7 +1030,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, | |||
| 986 | scmd)); | 1030 | scmd)); |
| 987 | } | 1031 | } |
| 988 | 1032 | ||
| 989 | return list_empty(work_q); | 1033 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
| 990 | } | 1034 | } |
| 991 | 1035 | ||
| 992 | /** | 1036 | /** |
| @@ -1137,6 +1181,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
| 1137 | struct list_head *done_q) | 1181 | struct list_head *done_q) |
| 1138 | { | 1182 | { |
| 1139 | LIST_HEAD(tmp_list); | 1183 | LIST_HEAD(tmp_list); |
| 1184 | LIST_HEAD(check_list); | ||
| 1140 | 1185 | ||
| 1141 | list_splice_init(work_q, &tmp_list); | 1186 | list_splice_init(work_q, &tmp_list); |
| 1142 | 1187 | ||
| @@ -1161,9 +1206,9 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
| 1161 | if (scmd_id(scmd) != id) | 1206 | if (scmd_id(scmd) != id) |
| 1162 | continue; | 1207 | continue; |
| 1163 | 1208 | ||
| 1164 | if ((rtn == SUCCESS || rtn == FAST_IO_FAIL) | 1209 | if (rtn == SUCCESS) |
| 1165 | && (!scsi_device_online(scmd->device) || | 1210 | list_move_tail(&scmd->eh_entry, &check_list); |
| 1166 | rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd))) | 1211 | else if (rtn == FAST_IO_FAIL) |
| 1167 | scsi_eh_finish_cmd(scmd, done_q); | 1212 | scsi_eh_finish_cmd(scmd, done_q); |
| 1168 | else | 1213 | else |
| 1169 | /* push back on work queue for further processing */ | 1214 | /* push back on work queue for further processing */ |
| @@ -1171,7 +1216,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, | |||
| 1171 | } | 1216 | } |
| 1172 | } | 1217 | } |
| 1173 | 1218 | ||
| 1174 | return list_empty(work_q); | 1219 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
| 1175 | } | 1220 | } |
| 1176 | 1221 | ||
| 1177 | /** | 1222 | /** |
| @@ -1185,6 +1230,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
| 1185 | struct list_head *done_q) | 1230 | struct list_head *done_q) |
| 1186 | { | 1231 | { |
| 1187 | struct scsi_cmnd *scmd, *chan_scmd, *next; | 1232 | struct scsi_cmnd *scmd, *chan_scmd, *next; |
| 1233 | LIST_HEAD(check_list); | ||
| 1188 | unsigned int channel; | 1234 | unsigned int channel; |
| 1189 | int rtn; | 1235 | int rtn; |
| 1190 | 1236 | ||
| @@ -1216,12 +1262,14 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
| 1216 | rtn = scsi_try_bus_reset(chan_scmd); | 1262 | rtn = scsi_try_bus_reset(chan_scmd); |
| 1217 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1263 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { |
| 1218 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1264 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
| 1219 | if (channel == scmd_channel(scmd)) | 1265 | if (channel == scmd_channel(scmd)) { |
| 1220 | if (!scsi_device_online(scmd->device) || | 1266 | if (rtn == FAST_IO_FAIL) |
| 1221 | rtn == FAST_IO_FAIL || | ||
| 1222 | !scsi_eh_tur(scmd)) | ||
| 1223 | scsi_eh_finish_cmd(scmd, | 1267 | scsi_eh_finish_cmd(scmd, |
| 1224 | done_q); | 1268 | done_q); |
| 1269 | else | ||
| 1270 | list_move_tail(&scmd->eh_entry, | ||
| 1271 | &check_list); | ||
| 1272 | } | ||
| 1225 | } | 1273 | } |
| 1226 | } else { | 1274 | } else { |
| 1227 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" | 1275 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" |
| @@ -1230,7 +1278,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, | |||
| 1230 | channel)); | 1278 | channel)); |
| 1231 | } | 1279 | } |
| 1232 | } | 1280 | } |
| 1233 | return list_empty(work_q); | 1281 | return scsi_eh_test_devices(&check_list, work_q, done_q, 0); |
| 1234 | } | 1282 | } |
| 1235 | 1283 | ||
| 1236 | /** | 1284 | /** |
| @@ -1242,6 +1290,7 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
| 1242 | struct list_head *done_q) | 1290 | struct list_head *done_q) |
| 1243 | { | 1291 | { |
| 1244 | struct scsi_cmnd *scmd, *next; | 1292 | struct scsi_cmnd *scmd, *next; |
| 1293 | LIST_HEAD(check_list); | ||
| 1245 | int rtn; | 1294 | int rtn; |
| 1246 | 1295 | ||
| 1247 | if (!list_empty(work_q)) { | 1296 | if (!list_empty(work_q)) { |
| @@ -1252,12 +1301,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
| 1252 | , current->comm)); | 1301 | , current->comm)); |
| 1253 | 1302 | ||
| 1254 | rtn = scsi_try_host_reset(scmd); | 1303 | rtn = scsi_try_host_reset(scmd); |
| 1255 | if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { | 1304 | if (rtn == SUCCESS) { |
| 1305 | list_splice_init(work_q, &check_list); | ||
| 1306 | } else if (rtn == FAST_IO_FAIL) { | ||
| 1256 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { | 1307 | list_for_each_entry_safe(scmd, next, work_q, eh_entry) { |
| 1257 | if (!scsi_device_online(scmd->device) || | ||
| 1258 | rtn == FAST_IO_FAIL || | ||
| 1259 | (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) || | ||
| 1260 | !scsi_eh_tur(scmd)) | ||
| 1261 | scsi_eh_finish_cmd(scmd, done_q); | 1308 | scsi_eh_finish_cmd(scmd, done_q); |
| 1262 | } | 1309 | } |
| 1263 | } else { | 1310 | } else { |
| @@ -1266,7 +1313,7 @@ static int scsi_eh_host_reset(struct list_head *work_q, | |||
| 1266 | current->comm)); | 1313 | current->comm)); |
| 1267 | } | 1314 | } |
| 1268 | } | 1315 | } |
| 1269 | return list_empty(work_q); | 1316 | return scsi_eh_test_devices(&check_list, work_q, done_q, 1); |
| 1270 | } | 1317 | } |
| 1271 | 1318 | ||
| 1272 | /** | 1319 | /** |
diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c index b587289cfacb..2bea4f0b684a 100644 --- a/drivers/scsi/scsi_trace.c +++ b/drivers/scsi/scsi_trace.c | |||
| @@ -59,6 +59,10 @@ scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) | |||
| 59 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", | 59 | trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", |
| 60 | (unsigned long long)lba, (unsigned long long)txlen, | 60 | (unsigned long long)lba, (unsigned long long)txlen, |
| 61 | cdb[1] >> 5); | 61 | cdb[1] >> 5); |
| 62 | |||
| 63 | if (cdb[0] == WRITE_SAME) | ||
| 64 | trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); | ||
| 65 | |||
| 62 | trace_seq_putc(p, 0); | 66 | trace_seq_putc(p, 0); |
| 63 | 67 | ||
| 64 | return ret; | 68 | return ret; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bd0806e64e85..953773cb26d9 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -490,7 +490,8 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | |||
| 490 | unsigned int max_blocks = 0; | 490 | unsigned int max_blocks = 0; |
| 491 | 491 | ||
| 492 | q->limits.discard_zeroes_data = sdkp->lbprz; | 492 | q->limits.discard_zeroes_data = sdkp->lbprz; |
| 493 | q->limits.discard_alignment = sdkp->unmap_alignment; | 493 | q->limits.discard_alignment = sdkp->unmap_alignment * |
| 494 | logical_block_size; | ||
| 494 | q->limits.discard_granularity = | 495 | q->limits.discard_granularity = |
| 495 | max(sdkp->physical_block_size, | 496 | max(sdkp->physical_block_size, |
| 496 | sdkp->unmap_granularity * logical_block_size); | 497 | sdkp->unmap_granularity * logical_block_size); |
| @@ -2021,16 +2022,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2021 | 2022 | ||
| 2022 | int dbd; | 2023 | int dbd; |
| 2023 | int modepage; | 2024 | int modepage; |
| 2025 | int first_len; | ||
| 2024 | struct scsi_mode_data data; | 2026 | struct scsi_mode_data data; |
| 2025 | struct scsi_sense_hdr sshdr; | 2027 | struct scsi_sense_hdr sshdr; |
| 2026 | int old_wce = sdkp->WCE; | 2028 | int old_wce = sdkp->WCE; |
| 2027 | int old_rcd = sdkp->RCD; | 2029 | int old_rcd = sdkp->RCD; |
| 2028 | int old_dpofua = sdkp->DPOFUA; | 2030 | int old_dpofua = sdkp->DPOFUA; |
| 2029 | 2031 | ||
| 2030 | if (sdp->skip_ms_page_8) | 2032 | first_len = 4; |
| 2031 | goto defaults; | 2033 | if (sdp->skip_ms_page_8) { |
| 2032 | 2034 | if (sdp->type == TYPE_RBC) | |
| 2033 | if (sdp->type == TYPE_RBC) { | 2035 | goto defaults; |
| 2036 | else { | ||
| 2037 | if (sdp->skip_ms_page_3f) | ||
| 2038 | goto defaults; | ||
| 2039 | modepage = 0x3F; | ||
| 2040 | if (sdp->use_192_bytes_for_3f) | ||
| 2041 | first_len = 192; | ||
| 2042 | dbd = 0; | ||
| 2043 | } | ||
| 2044 | } else if (sdp->type == TYPE_RBC) { | ||
| 2034 | modepage = 6; | 2045 | modepage = 6; |
| 2035 | dbd = 8; | 2046 | dbd = 8; |
| 2036 | } else { | 2047 | } else { |
| @@ -2039,13 +2050,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2039 | } | 2050 | } |
| 2040 | 2051 | ||
| 2041 | /* cautiously ask */ | 2052 | /* cautiously ask */ |
| 2042 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); | 2053 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, first_len, |
| 2054 | &data, &sshdr); | ||
| 2043 | 2055 | ||
| 2044 | if (!scsi_status_is_good(res)) | 2056 | if (!scsi_status_is_good(res)) |
| 2045 | goto bad_sense; | 2057 | goto bad_sense; |
| 2046 | 2058 | ||
| 2047 | if (!data.header_length) { | 2059 | if (!data.header_length) { |
| 2048 | modepage = 6; | 2060 | modepage = 6; |
| 2061 | first_len = 0; | ||
| 2049 | sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); | 2062 | sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); |
| 2050 | } | 2063 | } |
| 2051 | 2064 | ||
| @@ -2058,30 +2071,61 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2058 | */ | 2071 | */ |
| 2059 | if (len < 3) | 2072 | if (len < 3) |
| 2060 | goto bad_sense; | 2073 | goto bad_sense; |
| 2061 | if (len > 20) | 2074 | else if (len > SD_BUF_SIZE) { |
| 2062 | len = 20; | 2075 | sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " |
| 2063 | 2076 | "data from %d to %d bytes\n", len, SD_BUF_SIZE); | |
| 2064 | /* Take headers and block descriptors into account */ | 2077 | len = SD_BUF_SIZE; |
| 2065 | len += data.header_length + data.block_descriptor_length; | 2078 | } |
| 2066 | if (len > SD_BUF_SIZE) | 2079 | if (modepage == 0x3F && sdp->use_192_bytes_for_3f) |
| 2067 | goto bad_sense; | 2080 | len = 192; |
| 2068 | 2081 | ||
| 2069 | /* Get the data */ | 2082 | /* Get the data */ |
| 2070 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 2083 | if (len > first_len) |
| 2084 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, | ||
| 2085 | &data, &sshdr); | ||
| 2071 | 2086 | ||
| 2072 | if (scsi_status_is_good(res)) { | 2087 | if (scsi_status_is_good(res)) { |
| 2073 | int offset = data.header_length + data.block_descriptor_length; | 2088 | int offset = data.header_length + data.block_descriptor_length; |
| 2074 | 2089 | ||
| 2075 | if (offset >= SD_BUF_SIZE - 2) { | 2090 | while (offset < len) { |
| 2076 | sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); | 2091 | u8 page_code = buffer[offset] & 0x3F; |
| 2077 | goto defaults; | 2092 | u8 spf = buffer[offset] & 0x40; |
| 2093 | |||
| 2094 | if (page_code == 8 || page_code == 6) { | ||
| 2095 | /* We're interested only in the first 3 bytes. | ||
| 2096 | */ | ||
| 2097 | if (len - offset <= 2) { | ||
| 2098 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
| 2099 | "mode parameter data\n"); | ||
| 2100 | goto defaults; | ||
| 2101 | } else { | ||
| 2102 | modepage = page_code; | ||
| 2103 | goto Page_found; | ||
| 2104 | } | ||
| 2105 | } else { | ||
| 2106 | /* Go to the next page */ | ||
| 2107 | if (spf && len - offset > 3) | ||
| 2108 | offset += 4 + (buffer[offset+2] << 8) + | ||
| 2109 | buffer[offset+3]; | ||
| 2110 | else if (!spf && len - offset > 1) | ||
| 2111 | offset += 2 + buffer[offset+1]; | ||
| 2112 | else { | ||
| 2113 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
| 2114 | "mode parameter data\n"); | ||
| 2115 | goto defaults; | ||
| 2116 | } | ||
| 2117 | } | ||
| 2078 | } | 2118 | } |
| 2079 | 2119 | ||
| 2080 | if ((buffer[offset] & 0x3f) != modepage) { | 2120 | if (modepage == 0x3F) { |
| 2121 | sd_printk(KERN_ERR, sdkp, "No Caching mode page " | ||
| 2122 | "present\n"); | ||
| 2123 | goto defaults; | ||
| 2124 | } else if ((buffer[offset] & 0x3f) != modepage) { | ||
| 2081 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); | 2125 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); |
| 2082 | goto defaults; | 2126 | goto defaults; |
| 2083 | } | 2127 | } |
| 2084 | 2128 | Page_found: | |
| 2085 | if (modepage == 8) { | 2129 | if (modepage == 8) { |
| 2086 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); | 2130 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); |
| 2087 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); | 2131 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); |
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 9f4b58b7daad..7e22b737dfd8 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c | |||
| @@ -307,7 +307,7 @@ static inline int find_and_clear_bit_16(unsigned long *field) | |||
| 307 | "0: bsfw %1,%w0\n\t" | 307 | "0: bsfw %1,%w0\n\t" |
| 308 | "btr %0,%1\n\t" | 308 | "btr %0,%1\n\t" |
| 309 | "jnc 0b" | 309 | "jnc 0b" |
| 310 | : "=&r" (rv), "=m" (*field) :); | 310 | : "=&r" (rv), "+m" (*field) :); |
| 311 | 311 | ||
| 312 | return rv; | 312 | return rv; |
| 313 | } | 313 | } |
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index aed4e464d31c..dee2a2c909f5 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <scsi/scsi_host.h> | 31 | #include <scsi/scsi_host.h> |
| 32 | #include <scsi/scsi_device.h> | 32 | #include <scsi/scsi_device.h> |
| 33 | #include <scsi/scsi_cmnd.h> | 33 | #include <scsi/scsi_cmnd.h> |
| 34 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 34 | #include <scsi/scsi_tcq.h> |
| 35 | 35 | ||
| 36 | #include <target/target_core_base.h> | 36 | #include <target/target_core_base.h> |
| 37 | #include <target/target_core_transport.h> | 37 | #include <target/target_core_transport.h> |
| @@ -95,17 +95,17 @@ static struct se_cmd *tcm_loop_allocate_core_cmd( | |||
| 95 | if (sc->device->tagged_supported) { | 95 | if (sc->device->tagged_supported) { |
| 96 | switch (sc->tag) { | 96 | switch (sc->tag) { |
| 97 | case HEAD_OF_QUEUE_TAG: | 97 | case HEAD_OF_QUEUE_TAG: |
| 98 | sam_task_attr = TASK_ATTR_HOQ; | 98 | sam_task_attr = MSG_HEAD_TAG; |
| 99 | break; | 99 | break; |
| 100 | case ORDERED_QUEUE_TAG: | 100 | case ORDERED_QUEUE_TAG: |
| 101 | sam_task_attr = TASK_ATTR_ORDERED; | 101 | sam_task_attr = MSG_ORDERED_TAG; |
| 102 | break; | 102 | break; |
| 103 | default: | 103 | default: |
| 104 | sam_task_attr = TASK_ATTR_SIMPLE; | 104 | sam_task_attr = MSG_SIMPLE_TAG; |
| 105 | break; | 105 | break; |
| 106 | } | 106 | } |
| 107 | } else | 107 | } else |
| 108 | sam_task_attr = TASK_ATTR_SIMPLE; | 108 | sam_task_attr = MSG_SIMPLE_TAG; |
| 109 | 109 | ||
| 110 | /* | 110 | /* |
| 111 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure | 111 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure |
| @@ -379,7 +379,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) | |||
| 379 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure | 379 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure |
| 380 | */ | 380 | */ |
| 381 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, | 381 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, |
| 382 | DMA_NONE, TASK_ATTR_SIMPLE, | 382 | DMA_NONE, MSG_SIMPLE_TAG, |
| 383 | &tl_cmd->tl_sense_buf[0]); | 383 | &tl_cmd->tl_sense_buf[0]); |
| 384 | /* | 384 | /* |
| 385 | * Allocate the LUN_RESET TMR | 385 | * Allocate the LUN_RESET TMR |
| @@ -939,18 +939,6 @@ static u16 tcm_loop_get_fabric_sense_len(void) | |||
| 939 | return 0; | 939 | return 0; |
| 940 | } | 940 | } |
| 941 | 941 | ||
| 942 | static u64 tcm_loop_pack_lun(unsigned int lun) | ||
| 943 | { | ||
| 944 | u64 result; | ||
| 945 | |||
| 946 | /* LSB of lun into byte 1 big-endian */ | ||
| 947 | result = ((lun & 0xff) << 8); | ||
| 948 | /* use flat space addressing method */ | ||
| 949 | result |= 0x40 | ((lun >> 8) & 0x3f); | ||
| 950 | |||
| 951 | return cpu_to_le64(result); | ||
| 952 | } | ||
| 953 | |||
| 954 | static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) | 942 | static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) |
| 955 | { | 943 | { |
| 956 | switch (tl_hba->tl_proto_id) { | 944 | switch (tl_hba->tl_proto_id) { |
| @@ -1481,7 +1469,6 @@ static int tcm_loop_register_configfs(void) | |||
| 1481 | fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; | 1469 | fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; |
| 1482 | fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; | 1470 | fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; |
| 1483 | fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove; | 1471 | fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove; |
| 1484 | fabric->tf_ops.pack_lun = &tcm_loop_pack_lun; | ||
| 1485 | 1472 | ||
| 1486 | tf_cg = &fabric->tf_group; | 1473 | tf_cg = &fabric->tf_group; |
| 1487 | /* | 1474 | /* |
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index a5f44a6e6e1d..ee6fad979b50 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
| @@ -497,10 +497,6 @@ static int target_fabric_tf_ops_check( | |||
| 497 | printk(KERN_ERR "Missing tfo->is_state_remove()\n"); | 497 | printk(KERN_ERR "Missing tfo->is_state_remove()\n"); |
| 498 | return -EINVAL; | 498 | return -EINVAL; |
| 499 | } | 499 | } |
| 500 | if (!(tfo->pack_lun)) { | ||
| 501 | printk(KERN_ERR "Missing tfo->pack_lun()\n"); | ||
| 502 | return -EINVAL; | ||
| 503 | } | ||
| 504 | /* | 500 | /* |
| 505 | * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() | 501 | * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() |
| 506 | * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in | 502 | * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index d25e20829012..8407f9ca2b31 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
| 39 | #include <net/tcp.h> | 39 | #include <net/tcp.h> |
| 40 | #include <scsi/scsi.h> | 40 | #include <scsi/scsi.h> |
| 41 | #include <scsi/scsi_device.h> | ||
| 41 | 42 | ||
| 42 | #include <target/target_core_base.h> | 43 | #include <target/target_core_base.h> |
| 43 | #include <target/target_core_device.h> | 44 | #include <target/target_core_device.h> |
| @@ -150,13 +151,13 @@ out: | |||
| 150 | 151 | ||
| 151 | { | 152 | { |
| 152 | struct se_device *dev = se_lun->lun_se_dev; | 153 | struct se_device *dev = se_lun->lun_se_dev; |
| 153 | spin_lock(&dev->stats_lock); | 154 | spin_lock_irq(&dev->stats_lock); |
| 154 | dev->num_cmds++; | 155 | dev->num_cmds++; |
| 155 | if (se_cmd->data_direction == DMA_TO_DEVICE) | 156 | if (se_cmd->data_direction == DMA_TO_DEVICE) |
| 156 | dev->write_bytes += se_cmd->data_length; | 157 | dev->write_bytes += se_cmd->data_length; |
| 157 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) | 158 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) |
| 158 | dev->read_bytes += se_cmd->data_length; | 159 | dev->read_bytes += se_cmd->data_length; |
| 159 | spin_unlock(&dev->stats_lock); | 160 | spin_unlock_irq(&dev->stats_lock); |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | /* | 163 | /* |
| @@ -658,8 +659,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
| 658 | struct se_session *se_sess = SE_SESS(se_cmd); | 659 | struct se_session *se_sess = SE_SESS(se_cmd); |
| 659 | struct se_task *se_task; | 660 | struct se_task *se_task; |
| 660 | unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf; | 661 | unsigned char *buf = (unsigned char *)T_TASK(se_cmd)->t_task_buf; |
| 661 | u32 cdb_offset = 0, lun_count = 0, offset = 8; | 662 | u32 cdb_offset = 0, lun_count = 0, offset = 8, i; |
| 662 | u64 i, lun; | ||
| 663 | 663 | ||
| 664 | list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list) | 664 | list_for_each_entry(se_task, &T_TASK(se_cmd)->t_task_list, t_list) |
| 665 | break; | 665 | break; |
| @@ -675,15 +675,7 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
| 675 | * a $FABRIC_MOD. In that case, report LUN=0 only. | 675 | * a $FABRIC_MOD. In that case, report LUN=0 only. |
| 676 | */ | 676 | */ |
| 677 | if (!(se_sess)) { | 677 | if (!(se_sess)) { |
| 678 | lun = 0; | 678 | int_to_scsilun(0, (struct scsi_lun *)&buf[offset]); |
| 679 | buf[offset++] = ((lun >> 56) & 0xff); | ||
| 680 | buf[offset++] = ((lun >> 48) & 0xff); | ||
| 681 | buf[offset++] = ((lun >> 40) & 0xff); | ||
| 682 | buf[offset++] = ((lun >> 32) & 0xff); | ||
| 683 | buf[offset++] = ((lun >> 24) & 0xff); | ||
| 684 | buf[offset++] = ((lun >> 16) & 0xff); | ||
| 685 | buf[offset++] = ((lun >> 8) & 0xff); | ||
| 686 | buf[offset++] = (lun & 0xff); | ||
| 687 | lun_count = 1; | 679 | lun_count = 1; |
| 688 | goto done; | 680 | goto done; |
| 689 | } | 681 | } |
| @@ -703,15 +695,8 @@ int transport_core_report_lun_response(struct se_cmd *se_cmd) | |||
| 703 | if ((cdb_offset + 8) >= se_cmd->data_length) | 695 | if ((cdb_offset + 8) >= se_cmd->data_length) |
| 704 | continue; | 696 | continue; |
| 705 | 697 | ||
| 706 | lun = cpu_to_be64(CMD_TFO(se_cmd)->pack_lun(deve->mapped_lun)); | 698 | int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); |
| 707 | buf[offset++] = ((lun >> 56) & 0xff); | 699 | offset += 8; |
| 708 | buf[offset++] = ((lun >> 48) & 0xff); | ||
| 709 | buf[offset++] = ((lun >> 40) & 0xff); | ||
| 710 | buf[offset++] = ((lun >> 32) & 0xff); | ||
| 711 | buf[offset++] = ((lun >> 24) & 0xff); | ||
| 712 | buf[offset++] = ((lun >> 16) & 0xff); | ||
| 713 | buf[offset++] = ((lun >> 8) & 0xff); | ||
| 714 | buf[offset++] = (lun & 0xff); | ||
| 715 | cdb_offset += 8; | 700 | cdb_offset += 8; |
| 716 | } | 701 | } |
| 717 | spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock); | 702 | spin_unlock_irq(&SE_NODE_ACL(se_sess)->device_list_lock); |
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 7ff6a35f26ac..331d423fd0e0 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #include <scsi/scsi_device.h> | 41 | #include <scsi/scsi_device.h> |
| 42 | #include <scsi/scsi_cmnd.h> | 42 | #include <scsi/scsi_cmnd.h> |
| 43 | #include <scsi/scsi_host.h> | 43 | #include <scsi/scsi_host.h> |
| 44 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 44 | #include <scsi/scsi_tcq.h> |
| 45 | 45 | ||
| 46 | #include <target/target_core_base.h> | 46 | #include <target/target_core_base.h> |
| 47 | #include <target/target_core_device.h> | 47 | #include <target/target_core_device.h> |
| @@ -911,7 +911,7 @@ static int pscsi_do_task(struct se_task *task) | |||
| 911 | * descriptor | 911 | * descriptor |
| 912 | */ | 912 | */ |
| 913 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, | 913 | blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req, |
| 914 | (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ), | 914 | (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG), |
| 915 | pscsi_req_done); | 915 | pscsi_req_done); |
| 916 | 916 | ||
| 917 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | 917 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; |
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 4a109835e420..59b8b9c5ad72 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c | |||
| @@ -55,7 +55,8 @@ struct se_tmr_req *core_tmr_alloc_req( | |||
| 55 | { | 55 | { |
| 56 | struct se_tmr_req *tmr; | 56 | struct se_tmr_req *tmr; |
| 57 | 57 | ||
| 58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL); | 58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ? |
| 59 | GFP_ATOMIC : GFP_KERNEL); | ||
| 59 | if (!(tmr)) { | 60 | if (!(tmr)) { |
| 60 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); | 61 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); |
| 61 | return ERR_PTR(-ENOMEM); | 62 | return ERR_PTR(-ENOMEM); |
| @@ -398,9 +399,9 @@ int core_tmr_lun_reset( | |||
| 398 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); | 399 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); |
| 399 | } | 400 | } |
| 400 | 401 | ||
| 401 | spin_lock(&dev->stats_lock); | 402 | spin_lock_irq(&dev->stats_lock); |
| 402 | dev->num_resets++; | 403 | dev->num_resets++; |
| 403 | spin_unlock(&dev->stats_lock); | 404 | spin_unlock_irq(&dev->stats_lock); |
| 404 | 405 | ||
| 405 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", | 406 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", |
| 406 | (preempt_and_abort_list) ? "Preempt" : "TMR", | 407 | (preempt_and_abort_list) ? "Preempt" : "TMR", |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index b9d3501bdd91..4dafeb8b5638 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | #include <net/tcp.h> | 42 | #include <net/tcp.h> |
| 43 | #include <scsi/scsi.h> | 43 | #include <scsi/scsi.h> |
| 44 | #include <scsi/scsi_cmnd.h> | 44 | #include <scsi/scsi_cmnd.h> |
| 45 | #include <scsi/libsas.h> /* For TASK_ATTR_* */ | 45 | #include <scsi/scsi_tcq.h> |
| 46 | 46 | ||
| 47 | #include <target/target_core_base.h> | 47 | #include <target/target_core_base.h> |
| 48 | #include <target/target_core_device.h> | 48 | #include <target/target_core_device.h> |
| @@ -762,7 +762,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) | |||
| 762 | transport_all_task_dev_remove_state(cmd); | 762 | transport_all_task_dev_remove_state(cmd); |
| 763 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); | 763 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); |
| 764 | 764 | ||
| 765 | transport_free_dev_tasks(cmd); | ||
| 766 | 765 | ||
| 767 | check_lun: | 766 | check_lun: |
| 768 | spin_lock_irqsave(&lun->lun_cmd_lock, flags); | 767 | spin_lock_irqsave(&lun->lun_cmd_lock, flags); |
| @@ -1075,7 +1074,7 @@ static inline int transport_add_task_check_sam_attr( | |||
| 1075 | * head of the struct se_device->execute_task_list, and task_prev | 1074 | * head of the struct se_device->execute_task_list, and task_prev |
| 1076 | * after that for each subsequent task | 1075 | * after that for each subsequent task |
| 1077 | */ | 1076 | */ |
| 1078 | if (task->task_se_cmd->sam_task_attr == TASK_ATTR_HOQ) { | 1077 | if (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG) { |
| 1079 | list_add(&task->t_execute_list, | 1078 | list_add(&task->t_execute_list, |
| 1080 | (task_prev != NULL) ? | 1079 | (task_prev != NULL) ? |
| 1081 | &task_prev->t_execute_list : | 1080 | &task_prev->t_execute_list : |
| @@ -1195,6 +1194,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) | |||
| 1195 | break; | 1194 | break; |
| 1196 | 1195 | ||
| 1197 | list_del(&task->t_execute_list); | 1196 | list_del(&task->t_execute_list); |
| 1197 | atomic_set(&task->task_execute_queue, 0); | ||
| 1198 | atomic_dec(&dev->execute_tasks); | 1198 | atomic_dec(&dev->execute_tasks); |
| 1199 | 1199 | ||
| 1200 | return task; | 1200 | return task; |
| @@ -1210,8 +1210,14 @@ void transport_remove_task_from_execute_queue( | |||
| 1210 | { | 1210 | { |
| 1211 | unsigned long flags; | 1211 | unsigned long flags; |
| 1212 | 1212 | ||
| 1213 | if (atomic_read(&task->task_execute_queue) == 0) { | ||
| 1214 | dump_stack(); | ||
| 1215 | return; | ||
| 1216 | } | ||
| 1217 | |||
| 1213 | spin_lock_irqsave(&dev->execute_task_lock, flags); | 1218 | spin_lock_irqsave(&dev->execute_task_lock, flags); |
| 1214 | list_del(&task->t_execute_list); | 1219 | list_del(&task->t_execute_list); |
| 1220 | atomic_set(&task->task_execute_queue, 0); | ||
| 1215 | atomic_dec(&dev->execute_tasks); | 1221 | atomic_dec(&dev->execute_tasks); |
| 1216 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); | 1222 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); |
| 1217 | } | 1223 | } |
| @@ -1867,7 +1873,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) | |||
| 1867 | if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) | 1873 | if (SE_DEV(cmd)->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) |
| 1868 | return 0; | 1874 | return 0; |
| 1869 | 1875 | ||
| 1870 | if (cmd->sam_task_attr == TASK_ATTR_ACA) { | 1876 | if (cmd->sam_task_attr == MSG_ACA_TAG) { |
| 1871 | DEBUG_STA("SAM Task Attribute ACA" | 1877 | DEBUG_STA("SAM Task Attribute ACA" |
| 1872 | " emulation is not supported\n"); | 1878 | " emulation is not supported\n"); |
| 1873 | return -1; | 1879 | return -1; |
| @@ -2058,6 +2064,13 @@ int transport_generic_handle_tmr( | |||
| 2058 | } | 2064 | } |
| 2059 | EXPORT_SYMBOL(transport_generic_handle_tmr); | 2065 | EXPORT_SYMBOL(transport_generic_handle_tmr); |
| 2060 | 2066 | ||
| 2067 | void transport_generic_free_cmd_intr( | ||
| 2068 | struct se_cmd *cmd) | ||
| 2069 | { | ||
| 2070 | transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR); | ||
| 2071 | } | ||
| 2072 | EXPORT_SYMBOL(transport_generic_free_cmd_intr); | ||
| 2073 | |||
| 2061 | static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) | 2074 | static int transport_stop_tasks_for_cmd(struct se_cmd *cmd) |
| 2062 | { | 2075 | { |
| 2063 | struct se_task *task, *task_tmp; | 2076 | struct se_task *task, *task_tmp; |
| @@ -2504,7 +2517,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) | |||
| 2504 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 | 2517 | * Check for the existence of HEAD_OF_QUEUE, and if true return 1 |
| 2505 | * to allow the passed struct se_cmd list of tasks to the front of the list. | 2518 | * to allow the passed struct se_cmd list of tasks to the front of the list. |
| 2506 | */ | 2519 | */ |
| 2507 | if (cmd->sam_task_attr == TASK_ATTR_HOQ) { | 2520 | if (cmd->sam_task_attr == MSG_HEAD_TAG) { |
| 2508 | atomic_inc(&SE_DEV(cmd)->dev_hoq_count); | 2521 | atomic_inc(&SE_DEV(cmd)->dev_hoq_count); |
| 2509 | smp_mb__after_atomic_inc(); | 2522 | smp_mb__after_atomic_inc(); |
| 2510 | DEBUG_STA("Added HEAD_OF_QUEUE for CDB:" | 2523 | DEBUG_STA("Added HEAD_OF_QUEUE for CDB:" |
| @@ -2512,7 +2525,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd) | |||
| 2512 | T_TASK(cmd)->t_task_cdb[0], | 2525 | T_TASK(cmd)->t_task_cdb[0], |
| 2513 | cmd->se_ordered_id); | 2526 | cmd->se_ordered_id); |
| 2514 | return 1; | 2527 | return 1; |
| 2515 | } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { | 2528 | } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { |
| 2516 | spin_lock(&SE_DEV(cmd)->ordered_cmd_lock); | 2529 | spin_lock(&SE_DEV(cmd)->ordered_cmd_lock); |
| 2517 | list_add_tail(&cmd->se_ordered_list, | 2530 | list_add_tail(&cmd->se_ordered_list, |
| 2518 | &SE_DEV(cmd)->ordered_cmd_list); | 2531 | &SE_DEV(cmd)->ordered_cmd_list); |
| @@ -3411,7 +3424,7 @@ static int transport_generic_cmd_sequencer( | |||
| 3411 | * See spc4r17 section 5.3 | 3424 | * See spc4r17 section 5.3 |
| 3412 | */ | 3425 | */ |
| 3413 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 3426 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) |
| 3414 | cmd->sam_task_attr = TASK_ATTR_HOQ; | 3427 | cmd->sam_task_attr = MSG_HEAD_TAG; |
| 3415 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; | 3428 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; |
| 3416 | break; | 3429 | break; |
| 3417 | case READ_BUFFER: | 3430 | case READ_BUFFER: |
| @@ -3619,7 +3632,7 @@ static int transport_generic_cmd_sequencer( | |||
| 3619 | * See spc4r17 section 5.3 | 3632 | * See spc4r17 section 5.3 |
| 3620 | */ | 3633 | */ |
| 3621 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 3634 | if (SE_DEV(cmd)->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) |
| 3622 | cmd->sam_task_attr = TASK_ATTR_HOQ; | 3635 | cmd->sam_task_attr = MSG_HEAD_TAG; |
| 3623 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; | 3636 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_NONSG_IO_CDB; |
| 3624 | break; | 3637 | break; |
| 3625 | default: | 3638 | default: |
| @@ -3777,21 +3790,21 @@ static void transport_complete_task_attr(struct se_cmd *cmd) | |||
| 3777 | struct se_cmd *cmd_p, *cmd_tmp; | 3790 | struct se_cmd *cmd_p, *cmd_tmp; |
| 3778 | int new_active_tasks = 0; | 3791 | int new_active_tasks = 0; |
| 3779 | 3792 | ||
| 3780 | if (cmd->sam_task_attr == TASK_ATTR_SIMPLE) { | 3793 | if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { |
| 3781 | atomic_dec(&dev->simple_cmds); | 3794 | atomic_dec(&dev->simple_cmds); |
| 3782 | smp_mb__after_atomic_dec(); | 3795 | smp_mb__after_atomic_dec(); |
| 3783 | dev->dev_cur_ordered_id++; | 3796 | dev->dev_cur_ordered_id++; |
| 3784 | DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for" | 3797 | DEBUG_STA("Incremented dev->dev_cur_ordered_id: %u for" |
| 3785 | " SIMPLE: %u\n", dev->dev_cur_ordered_id, | 3798 | " SIMPLE: %u\n", dev->dev_cur_ordered_id, |
| 3786 | cmd->se_ordered_id); | 3799 | cmd->se_ordered_id); |
| 3787 | } else if (cmd->sam_task_attr == TASK_ATTR_HOQ) { | 3800 | } else if (cmd->sam_task_attr == MSG_HEAD_TAG) { |
| 3788 | atomic_dec(&dev->dev_hoq_count); | 3801 | atomic_dec(&dev->dev_hoq_count); |
| 3789 | smp_mb__after_atomic_dec(); | 3802 | smp_mb__after_atomic_dec(); |
| 3790 | dev->dev_cur_ordered_id++; | 3803 | dev->dev_cur_ordered_id++; |
| 3791 | DEBUG_STA("Incremented dev_cur_ordered_id: %u for" | 3804 | DEBUG_STA("Incremented dev_cur_ordered_id: %u for" |
| 3792 | " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, | 3805 | " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id, |
| 3793 | cmd->se_ordered_id); | 3806 | cmd->se_ordered_id); |
| 3794 | } else if (cmd->sam_task_attr == TASK_ATTR_ORDERED) { | 3807 | } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) { |
| 3795 | spin_lock(&dev->ordered_cmd_lock); | 3808 | spin_lock(&dev->ordered_cmd_lock); |
| 3796 | list_del(&cmd->se_ordered_list); | 3809 | list_del(&cmd->se_ordered_list); |
| 3797 | atomic_dec(&dev->dev_ordered_sync); | 3810 | atomic_dec(&dev->dev_ordered_sync); |
| @@ -3824,7 +3837,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd) | |||
| 3824 | new_active_tasks++; | 3837 | new_active_tasks++; |
| 3825 | 3838 | ||
| 3826 | spin_lock(&dev->delayed_cmd_lock); | 3839 | spin_lock(&dev->delayed_cmd_lock); |
| 3827 | if (cmd_p->sam_task_attr == TASK_ATTR_ORDERED) | 3840 | if (cmd_p->sam_task_attr == MSG_ORDERED_TAG) |
| 3828 | break; | 3841 | break; |
| 3829 | } | 3842 | } |
| 3830 | spin_unlock(&dev->delayed_cmd_lock); | 3843 | spin_unlock(&dev->delayed_cmd_lock); |
| @@ -4776,18 +4789,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
| 4776 | sg_end_cur->page_link &= ~0x02; | 4789 | sg_end_cur->page_link &= ~0x02; |
| 4777 | 4790 | ||
| 4778 | sg_chain(sg_head, task_sg_num, sg_head_cur); | 4791 | sg_chain(sg_head, task_sg_num, sg_head_cur); |
| 4779 | sg_count += (task->task_sg_num + 1); | ||
| 4780 | } else | ||
| 4781 | sg_count += task->task_sg_num; | 4792 | sg_count += task->task_sg_num; |
| 4793 | task_sg_num = (task->task_sg_num + 1); | ||
| 4794 | } else { | ||
| 4795 | sg_chain(sg_head, task_sg_num, sg_head_cur); | ||
| 4796 | sg_count += task->task_sg_num; | ||
| 4797 | task_sg_num = task->task_sg_num; | ||
| 4798 | } | ||
| 4782 | 4799 | ||
| 4783 | sg_head = sg_head_cur; | 4800 | sg_head = sg_head_cur; |
| 4784 | sg_link = sg_link_cur; | 4801 | sg_link = sg_link_cur; |
| 4785 | task_sg_num = task->task_sg_num; | ||
| 4786 | continue; | 4802 | continue; |
| 4787 | } | 4803 | } |
| 4788 | sg_head = sg_first = &task->task_sg[0]; | 4804 | sg_head = sg_first = &task->task_sg[0]; |
| 4789 | sg_link = &task->task_sg[task->task_sg_num]; | 4805 | sg_link = &task->task_sg[task->task_sg_num]; |
| 4790 | task_sg_num = task->task_sg_num; | ||
| 4791 | /* | 4806 | /* |
| 4792 | * Check for single task.. | 4807 | * Check for single task.. |
| 4793 | */ | 4808 | */ |
| @@ -4798,9 +4813,12 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
| 4798 | */ | 4813 | */ |
| 4799 | sg_end = &task->task_sg[task->task_sg_num - 1]; | 4814 | sg_end = &task->task_sg[task->task_sg_num - 1]; |
| 4800 | sg_end->page_link &= ~0x02; | 4815 | sg_end->page_link &= ~0x02; |
| 4801 | sg_count += (task->task_sg_num + 1); | ||
| 4802 | } else | ||
| 4803 | sg_count += task->task_sg_num; | 4816 | sg_count += task->task_sg_num; |
| 4817 | task_sg_num = (task->task_sg_num + 1); | ||
| 4818 | } else { | ||
| 4819 | sg_count += task->task_sg_num; | ||
| 4820 | task_sg_num = task->task_sg_num; | ||
| 4821 | } | ||
| 4804 | } | 4822 | } |
| 4805 | /* | 4823 | /* |
| 4806 | * Setup the starting pointer and total t_tasks_sg_linked_no including | 4824 | * Setup the starting pointer and total t_tasks_sg_linked_no including |
| @@ -4809,21 +4827,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
| 4809 | T_TASK(cmd)->t_tasks_sg_chained = sg_first; | 4827 | T_TASK(cmd)->t_tasks_sg_chained = sg_first; |
| 4810 | T_TASK(cmd)->t_tasks_sg_chained_no = sg_count; | 4828 | T_TASK(cmd)->t_tasks_sg_chained_no = sg_count; |
| 4811 | 4829 | ||
| 4812 | DEBUG_CMD_M("Setup T_TASK(cmd)->t_tasks_sg_chained: %p and" | 4830 | DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and" |
| 4813 | " t_tasks_sg_chained_no: %u\n", T_TASK(cmd)->t_tasks_sg_chained, | 4831 | " t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained, |
| 4814 | T_TASK(cmd)->t_tasks_sg_chained_no); | 4832 | T_TASK(cmd)->t_tasks_sg_chained_no); |
| 4815 | 4833 | ||
| 4816 | for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg, | 4834 | for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg, |
| 4817 | T_TASK(cmd)->t_tasks_sg_chained_no, i) { | 4835 | T_TASK(cmd)->t_tasks_sg_chained_no, i) { |
| 4818 | 4836 | ||
| 4819 | DEBUG_CMD_M("SG: %p page: %p length: %d offset: %d\n", | 4837 | DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n", |
| 4820 | sg, sg_page(sg), sg->length, sg->offset); | 4838 | i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic); |
| 4821 | if (sg_is_chain(sg)) | 4839 | if (sg_is_chain(sg)) |
| 4822 | DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg); | 4840 | DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg); |
| 4823 | if (sg_is_last(sg)) | 4841 | if (sg_is_last(sg)) |
| 4824 | DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg); | 4842 | DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg); |
| 4825 | } | 4843 | } |
| 4826 | |||
| 4827 | } | 4844 | } |
| 4828 | EXPORT_SYMBOL(transport_do_task_sg_chain); | 4845 | EXPORT_SYMBOL(transport_do_task_sg_chain); |
| 4829 | 4846 | ||
| @@ -5297,6 +5314,8 @@ void transport_generic_free_cmd( | |||
| 5297 | if (wait_for_tasks && cmd->transport_wait_for_tasks) | 5314 | if (wait_for_tasks && cmd->transport_wait_for_tasks) |
| 5298 | cmd->transport_wait_for_tasks(cmd, 0, 0); | 5315 | cmd->transport_wait_for_tasks(cmd, 0, 0); |
| 5299 | 5316 | ||
| 5317 | transport_free_dev_tasks(cmd); | ||
| 5318 | |||
| 5300 | transport_generic_remove(cmd, release_to_pool, | 5319 | transport_generic_remove(cmd, release_to_pool, |
| 5301 | session_reinstatement); | 5320 | session_reinstatement); |
| 5302 | } | 5321 | } |
| @@ -6132,6 +6151,9 @@ get_cmd: | |||
| 6132 | case TRANSPORT_REMOVE: | 6151 | case TRANSPORT_REMOVE: |
| 6133 | transport_generic_remove(cmd, 1, 0); | 6152 | transport_generic_remove(cmd, 1, 0); |
| 6134 | break; | 6153 | break; |
| 6154 | case TRANSPORT_FREE_CMD_INTR: | ||
| 6155 | transport_generic_free_cmd(cmd, 0, 1, 0); | ||
| 6156 | break; | ||
| 6135 | case TRANSPORT_PROCESS_TMR: | 6157 | case TRANSPORT_PROCESS_TMR: |
| 6136 | transport_generic_do_tmr(cmd); | 6158 | transport_generic_do_tmr(cmd); |
| 6137 | break; | 6159 | break; |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 49e51778f733..c056a1132ae1 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <scsi/scsi_host.h> | 35 | #include <scsi/scsi_host.h> |
| 36 | #include <scsi/scsi_device.h> | 36 | #include <scsi/scsi_device.h> |
| 37 | #include <scsi/scsi_cmnd.h> | 37 | #include <scsi/scsi_cmnd.h> |
| 38 | #include <scsi/scsi_tcq.h> | ||
| 38 | #include <scsi/libfc.h> | 39 | #include <scsi/libfc.h> |
| 39 | #include <scsi/fc_encode.h> | 40 | #include <scsi/fc_encode.h> |
| 40 | 41 | ||
| @@ -592,8 +593,25 @@ static void ft_send_cmd(struct ft_cmd *cmd) | |||
| 592 | case FCP_CFL_WRDATA | FCP_CFL_RDDATA: | 593 | case FCP_CFL_WRDATA | FCP_CFL_RDDATA: |
| 593 | goto err; /* TBD not supported by tcm_fc yet */ | 594 | goto err; /* TBD not supported by tcm_fc yet */ |
| 594 | } | 595 | } |
| 596 | /* | ||
| 597 | * Locate the SAM Task Attr from fc_pri_ta | ||
| 598 | */ | ||
| 599 | switch (fcp->fc_pri_ta & FCP_PTA_MASK) { | ||
| 600 | case FCP_PTA_HEADQ: | ||
| 601 | task_attr = MSG_HEAD_TAG; | ||
| 602 | break; | ||
| 603 | case FCP_PTA_ORDERED: | ||
| 604 | task_attr = MSG_ORDERED_TAG; | ||
| 605 | break; | ||
| 606 | case FCP_PTA_ACA: | ||
| 607 | task_attr = MSG_ACA_TAG; | ||
| 608 | break; | ||
| 609 | case FCP_PTA_SIMPLE: /* Fallthrough */ | ||
| 610 | default: | ||
| 611 | task_attr = MSG_SIMPLE_TAG; | ||
| 612 | } | ||
| 613 | |||
| 595 | 614 | ||
| 596 | /* FCP_PTA_ maps 1:1 to TASK_ATTR_ */ | ||
| 597 | task_attr = fcp->fc_pri_ta & FCP_PTA_MASK; | 615 | task_attr = fcp->fc_pri_ta & FCP_PTA_MASK; |
| 598 | data_len = ntohl(fcp->fc_dl); | 616 | data_len = ntohl(fcp->fc_dl); |
| 599 | cmd->cdb = fcp->fc_cdb; | 617 | cmd->cdb = fcp->fc_cdb; |
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index fcdbbffe88cc..84e868c255dd 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c | |||
| @@ -519,13 +519,6 @@ static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg) | |||
| 519 | return tpg->index; | 519 | return tpg->index; |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | static u64 ft_pack_lun(unsigned int index) | ||
| 523 | { | ||
| 524 | WARN_ON(index >= 256); | ||
| 525 | /* Caller wants this byte-swapped */ | ||
| 526 | return cpu_to_le64((index & 0xff) << 8); | ||
| 527 | } | ||
| 528 | |||
| 529 | static struct target_core_fabric_ops ft_fabric_ops = { | 522 | static struct target_core_fabric_ops ft_fabric_ops = { |
| 530 | .get_fabric_name = ft_get_fabric_name, | 523 | .get_fabric_name = ft_get_fabric_name, |
| 531 | .get_fabric_proto_ident = fc_get_fabric_proto_ident, | 524 | .get_fabric_proto_ident = fc_get_fabric_proto_ident, |
| @@ -564,7 +557,6 @@ static struct target_core_fabric_ops ft_fabric_ops = { | |||
| 564 | .get_fabric_sense_len = ft_get_fabric_sense_len, | 557 | .get_fabric_sense_len = ft_get_fabric_sense_len, |
| 565 | .set_fabric_sense_len = ft_set_fabric_sense_len, | 558 | .set_fabric_sense_len = ft_set_fabric_sense_len, |
| 566 | .is_state_remove = ft_is_state_remove, | 559 | .is_state_remove = ft_is_state_remove, |
| 567 | .pack_lun = ft_pack_lun, | ||
| 568 | /* | 560 | /* |
| 569 | * Setup function pointers for generic logic in | 561 | * Setup function pointers for generic logic in |
| 570 | * target_core_fabric_configfs.c | 562 | * target_core_fabric_configfs.c |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 8f6bb9c7f3eb..ee866060f8a4 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
| @@ -604,6 +604,7 @@ struct sas_domain_function_template { | |||
| 604 | int (*lldd_clear_aca)(struct domain_device *, u8 *lun); | 604 | int (*lldd_clear_aca)(struct domain_device *, u8 *lun); |
| 605 | int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); | 605 | int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); |
| 606 | int (*lldd_I_T_nexus_reset)(struct domain_device *); | 606 | int (*lldd_I_T_nexus_reset)(struct domain_device *); |
| 607 | int (*lldd_ata_soft_reset)(struct domain_device *); | ||
| 607 | int (*lldd_lu_reset)(struct domain_device *, u8 *lun); | 608 | int (*lldd_lu_reset)(struct domain_device *, u8 *lun); |
| 608 | int (*lldd_query_task)(struct sas_task *); | 609 | int (*lldd_query_task)(struct sas_task *); |
| 609 | 610 | ||
diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h index d6e7994aa634..81dd12edc38c 100644 --- a/include/scsi/scsi_tcq.h +++ b/include/scsi/scsi_tcq.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #define MSG_SIMPLE_TAG 0x20 | 9 | #define MSG_SIMPLE_TAG 0x20 |
| 10 | #define MSG_HEAD_TAG 0x21 | 10 | #define MSG_HEAD_TAG 0x21 |
| 11 | #define MSG_ORDERED_TAG 0x22 | 11 | #define MSG_ORDERED_TAG 0x22 |
| 12 | #define MSG_ACA_TAG 0x24 /* unsupported */ | ||
| 12 | 13 | ||
| 13 | #define SCSI_NO_TAG (-1) /* identify no tag in use */ | 14 | #define SCSI_NO_TAG (-1) /* identify no tag in use */ |
| 14 | 15 | ||
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1d3b5b2f0dbc..561ac99def5a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -98,6 +98,7 @@ enum transport_state_table { | |||
| 98 | TRANSPORT_REMOVE = 14, | 98 | TRANSPORT_REMOVE = 14, |
| 99 | TRANSPORT_FREE = 15, | 99 | TRANSPORT_FREE = 15, |
| 100 | TRANSPORT_NEW_CMD_MAP = 16, | 100 | TRANSPORT_NEW_CMD_MAP = 16, |
| 101 | TRANSPORT_FREE_CMD_INTR = 17, | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | /* Used for struct se_cmd->se_cmd_flags */ | 104 | /* Used for struct se_cmd->se_cmd_flags */ |
diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index dc78f77f9450..747e1404dca0 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h | |||
| @@ -77,7 +77,6 @@ struct target_core_fabric_ops { | |||
| 77 | u16 (*set_fabric_sense_len)(struct se_cmd *, u32); | 77 | u16 (*set_fabric_sense_len)(struct se_cmd *, u32); |
| 78 | u16 (*get_fabric_sense_len)(void); | 78 | u16 (*get_fabric_sense_len)(void); |
| 79 | int (*is_state_remove)(struct se_cmd *); | 79 | int (*is_state_remove)(struct se_cmd *); |
| 80 | u64 (*pack_lun)(unsigned int); | ||
| 81 | /* | 80 | /* |
| 82 | * fabric module calls for target_core_fabric_configfs.c | 81 | * fabric module calls for target_core_fabric_configfs.c |
| 83 | */ | 82 | */ |
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 59aa464f6ee2..24a1c6cb83c3 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h | |||
| @@ -172,6 +172,7 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *); | |||
| 172 | extern int transport_generic_handle_data(struct se_cmd *); | 172 | extern int transport_generic_handle_data(struct se_cmd *); |
| 173 | extern void transport_new_cmd_failure(struct se_cmd *); | 173 | extern void transport_new_cmd_failure(struct se_cmd *); |
| 174 | extern int transport_generic_handle_tmr(struct se_cmd *); | 174 | extern int transport_generic_handle_tmr(struct se_cmd *); |
| 175 | extern void transport_generic_free_cmd_intr(struct se_cmd *); | ||
| 175 | extern void __transport_stop_task_timer(struct se_task *, unsigned long *); | 176 | extern void __transport_stop_task_timer(struct se_task *, unsigned long *); |
| 176 | extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]); | 177 | extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]); |
| 177 | extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, | 178 | extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32, |
