diff options
author | James Smart <james.smart@emulex.com> | 2011-07-22 18:37:42 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 07:14:00 -0400 |
commit | b76f2dc91c0fff7a66616affdc039dc2e4b7ff98 (patch) | |
tree | c918b99e5e368f32118044a3ecbb4e793443028c /drivers/scsi/lpfc | |
parent | 0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25 (diff) |
[SCSI] lpfc 8.3.25: Enhancements to Debug infrastructure
Enhancements to Debug infrastructure
- debugfs additions for new hardware.
- Correct stack overflow in lpfc_debugfs_dumpHBASlim_data()
- Correct warning on uninitialized reg_val in lpfc_idiag_drbacc_write()
- Separated the iDiag command for capturing mailbox commands for generic
issue mailbox command entry point and for BSG multi-buffer handling.
- Added capturing dumping capabiliy of mailbox command and external buffer
for the completion of the mailbox command so that the outcome can be
examined.
- Changed all the iDiag command structure data array indexing introduced so
far with properly defined macros.
- Added SLI4 device PCI BAR memory mapped register read/browse, write-by-
value, set-bit, and clear-bit methods for both interface type 0 and
interface type 2.
- Corrected warnings on mbxstatus being uninitialized in error paths in
lpfc_bsg.c
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 37 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 1354 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.h | 125 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 162 |
8 files changed, 1664 insertions, 36 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 0441361c79c8..b932067bf2d8 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -851,9 +851,13 @@ struct lpfc_hba { | |||
851 | /* iDiag debugfs sub-directory */ | 851 | /* iDiag debugfs sub-directory */ |
852 | struct dentry *idiag_root; | 852 | struct dentry *idiag_root; |
853 | struct dentry *idiag_pci_cfg; | 853 | struct dentry *idiag_pci_cfg; |
854 | struct dentry *idiag_bar_acc; | ||
854 | struct dentry *idiag_que_info; | 855 | struct dentry *idiag_que_info; |
855 | struct dentry *idiag_que_acc; | 856 | struct dentry *idiag_que_acc; |
856 | struct dentry *idiag_drb_acc; | 857 | struct dentry *idiag_drb_acc; |
858 | struct dentry *idiag_ctl_acc; | ||
859 | struct dentry *idiag_mbx_acc; | ||
860 | struct dentry *idiag_ext_acc; | ||
857 | #endif | 861 | #endif |
858 | 862 | ||
859 | /* Used for deferred freeing of ELS data buffers */ | 863 | /* Used for deferred freeing of ELS data buffers */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 80ca11c5158c..fa5bc146d67b 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -810,6 +810,7 @@ static ssize_t | |||
810 | lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) | 810 | lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) |
811 | { | 811 | { |
812 | struct completion online_compl; | 812 | struct completion online_compl; |
813 | struct pci_dev *pdev = phba->pcidev; | ||
813 | uint32_t reg_val; | 814 | uint32_t reg_val; |
814 | int status = 0; | 815 | int status = 0; |
815 | int rc; | 816 | int rc; |
@@ -822,6 +823,14 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) | |||
822 | LPFC_SLI_INTF_IF_TYPE_2)) | 823 | LPFC_SLI_INTF_IF_TYPE_2)) |
823 | return -EPERM; | 824 | return -EPERM; |
824 | 825 | ||
826 | if (!pdev->is_physfn) | ||
827 | return -EPERM; | ||
828 | |||
829 | /* Disable SR-IOV virtual functions if enabled */ | ||
830 | if (phba->cfg_sriov_nr_virtfn) { | ||
831 | pci_disable_sriov(pdev); | ||
832 | phba->cfg_sriov_nr_virtfn = 0; | ||
833 | } | ||
825 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 834 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
826 | 835 | ||
827 | if (status != 0) | 836 | if (status != 0) |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index f46378fb802c..6760c69f5253 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "lpfc.h" | 42 | #include "lpfc.h" |
43 | #include "lpfc_logmsg.h" | 43 | #include "lpfc_logmsg.h" |
44 | #include "lpfc_crtn.h" | 44 | #include "lpfc_crtn.h" |
45 | #include "lpfc_debugfs.h" | ||
45 | #include "lpfc_vport.h" | 46 | #include "lpfc_vport.h" |
46 | #include "lpfc_version.h" | 47 | #include "lpfc_version.h" |
47 | 48 | ||
@@ -1566,7 +1567,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1566 | uint32_t link_flags; | 1567 | uint32_t link_flags; |
1567 | uint32_t timeout; | 1568 | uint32_t timeout; |
1568 | LPFC_MBOXQ_t *pmboxq; | 1569 | LPFC_MBOXQ_t *pmboxq; |
1569 | int mbxstatus; | 1570 | int mbxstatus = MBX_SUCCESS; |
1570 | int i = 0; | 1571 | int i = 0; |
1571 | int rc = 0; | 1572 | int rc = 0; |
1572 | 1573 | ||
@@ -1740,7 +1741,7 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1740 | uint32_t link_flags, timeout, req_len, alloc_len; | 1741 | uint32_t link_flags, timeout, req_len, alloc_len; |
1741 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; | 1742 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; |
1742 | LPFC_MBOXQ_t *pmboxq = NULL; | 1743 | LPFC_MBOXQ_t *pmboxq = NULL; |
1743 | int mbxstatus, i, rc = 0; | 1744 | int mbxstatus = MBX_SUCCESS, i, rc = 0; |
1744 | 1745 | ||
1745 | /* no data to return just the return code */ | 1746 | /* no data to return just the return code */ |
1746 | job->reply->reply_payload_rcv_len = 0; | 1747 | job->reply->reply_payload_rcv_len = 0; |
@@ -3177,6 +3178,11 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
3177 | "(x%x/x%x) complete bsg job done, bsize:%d\n", | 3178 | "(x%x/x%x) complete bsg job done, bsize:%d\n", |
3178 | phba->mbox_ext_buf_ctx.nembType, | 3179 | phba->mbox_ext_buf_ctx.nembType, |
3179 | phba->mbox_ext_buf_ctx.mboxType, size); | 3180 | phba->mbox_ext_buf_ctx.mboxType, size); |
3181 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, | ||
3182 | phba->mbox_ext_buf_ctx.nembType, | ||
3183 | phba->mbox_ext_buf_ctx.mboxType, | ||
3184 | dma_ebuf, sta_pos_addr, | ||
3185 | phba->mbox_ext_buf_ctx.mbx_dmabuf, 0); | ||
3180 | } else | 3186 | } else |
3181 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 3187 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
3182 | 3188 | ||
@@ -3429,6 +3435,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3429 | "ext_buf_cnt:%d\n", ext_buf_cnt); | 3435 | "ext_buf_cnt:%d\n", ext_buf_cnt); |
3430 | } | 3436 | } |
3431 | 3437 | ||
3438 | /* before dma descriptor setup */ | ||
3439 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox, | ||
3440 | sta_pre_addr, dmabuf, ext_buf_cnt); | ||
3441 | |||
3432 | /* reject non-embedded mailbox command with none external buffer */ | 3442 | /* reject non-embedded mailbox command with none external buffer */ |
3433 | if (ext_buf_cnt == 0) { | 3443 | if (ext_buf_cnt == 0) { |
3434 | rc = -EPERM; | 3444 | rc = -EPERM; |
@@ -3476,6 +3486,10 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3476 | } | 3486 | } |
3477 | } | 3487 | } |
3478 | 3488 | ||
3489 | /* after dma descriptor setup */ | ||
3490 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_rd, dma_mbox, | ||
3491 | sta_pos_addr, dmabuf, ext_buf_cnt); | ||
3492 | |||
3479 | /* construct base driver mbox command */ | 3493 | /* construct base driver mbox command */ |
3480 | pmb = &pmboxq->u.mb; | 3494 | pmb = &pmboxq->u.mb; |
3481 | pmbx = (uint8_t *)dmabuf->virt; | 3495 | pmbx = (uint8_t *)dmabuf->virt; |
@@ -3590,12 +3604,20 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3590 | "ext_buf_cnt:%d\n", ext_buf_cnt); | 3604 | "ext_buf_cnt:%d\n", ext_buf_cnt); |
3591 | } | 3605 | } |
3592 | 3606 | ||
3607 | /* before dma buffer descriptor setup */ | ||
3608 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox, | ||
3609 | sta_pre_addr, dmabuf, ext_buf_cnt); | ||
3610 | |||
3593 | if (ext_buf_cnt == 0) | 3611 | if (ext_buf_cnt == 0) |
3594 | return -EPERM; | 3612 | return -EPERM; |
3595 | 3613 | ||
3596 | /* for the first external buffer */ | 3614 | /* for the first external buffer */ |
3597 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); | 3615 | lpfc_bsg_sli_cfg_dma_desc_setup(phba, nemb_tp, 0, dmabuf, dmabuf); |
3598 | 3616 | ||
3617 | /* after dma descriptor setup */ | ||
3618 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, nemb_tp, mbox_wr, dma_mbox, | ||
3619 | sta_pos_addr, dmabuf, ext_buf_cnt); | ||
3620 | |||
3599 | /* log for looking forward */ | 3621 | /* log for looking forward */ |
3600 | for (i = 1; i < ext_buf_cnt; i++) { | 3622 | for (i = 1; i < ext_buf_cnt; i++) { |
3601 | if (nemb_tp == nemb_mse) | 3623 | if (nemb_tp == nemb_mse) |
@@ -3844,6 +3866,12 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
3844 | dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list, | 3866 | dmabuf = list_first_entry(&phba->mbox_ext_buf_ctx.ext_dmabuf_list, |
3845 | struct lpfc_dmabuf, list); | 3867 | struct lpfc_dmabuf, list); |
3846 | list_del_init(&dmabuf->list); | 3868 | list_del_init(&dmabuf->list); |
3869 | |||
3870 | /* after dma buffer descriptor setup */ | ||
3871 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType, | ||
3872 | mbox_rd, dma_ebuf, sta_pos_addr, | ||
3873 | dmabuf, index); | ||
3874 | |||
3847 | pbuf = (uint8_t *)dmabuf->virt; | 3875 | pbuf = (uint8_t *)dmabuf->virt; |
3848 | job->reply->reply_payload_rcv_len = | 3876 | job->reply->reply_payload_rcv_len = |
3849 | sg_copy_from_buffer(job->reply_payload.sg_list, | 3877 | sg_copy_from_buffer(job->reply_payload.sg_list, |
@@ -3926,6 +3954,11 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
3926 | dmabuf); | 3954 | dmabuf); |
3927 | list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list); | 3955 | list_add_tail(&dmabuf->list, &phba->mbox_ext_buf_ctx.ext_dmabuf_list); |
3928 | 3956 | ||
3957 | /* after write dma buffer */ | ||
3958 | lpfc_idiag_mbxacc_dump_bsg_mbox(phba, phba->mbox_ext_buf_ctx.nembType, | ||
3959 | mbox_wr, dma_ebuf, sta_pos_addr, | ||
3960 | dmabuf, index); | ||
3961 | |||
3929 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { | 3962 | if (phba->mbox_ext_buf_ctx.seqNum == phba->mbox_ext_buf_ctx.numBuf) { |
3930 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | 3963 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, |
3931 | "2968 SLI_CONFIG ext-buffer wr all %d " | 3964 | "2968 SLI_CONFIG ext-buffer wr all %d " |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 1e41af8dea74..1f3cad0b1ce8 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -371,6 +371,10 @@ extern struct lpfc_hbq_init *lpfc_hbq_defs[]; | |||
371 | /* SLI4 if_type 2 externs. */ | 371 | /* SLI4 if_type 2 externs. */ |
372 | int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *); | 372 | int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *); |
373 | int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *); | 373 | int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *); |
374 | int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t, | ||
375 | uint16_t *, uint16_t *); | ||
376 | int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t, | ||
377 | uint16_t *, uint16_t *); | ||
374 | 378 | ||
375 | /* externs BlockGuard */ | 379 | /* externs BlockGuard */ |
376 | extern char *_dump_buf_data; | 380 | extern char *_dump_buf_data; |
@@ -437,6 +441,10 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); | |||
437 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); | 441 | void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); |
438 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, | 442 | struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, |
439 | uint32_t); | 443 | uint32_t); |
444 | void lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *, enum nemb_type, | ||
445 | enum mbox_type, enum dma_type, enum sta_type, | ||
446 | struct lpfc_dmabuf *, uint32_t); | ||
447 | void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *); | ||
440 | int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); | 448 | int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); |
441 | /* functions to support SR-IOV */ | 449 | /* functions to support SR-IOV */ |
442 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); | 450 | int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 30b25c5fdd7e..a0424dd90e40 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "lpfc_version.h" | 48 | #include "lpfc_version.h" |
49 | #include "lpfc_compat.h" | 49 | #include "lpfc_compat.h" |
50 | #include "lpfc_debugfs.h" | 50 | #include "lpfc_debugfs.h" |
51 | #include "lpfc_bsg.h" | ||
51 | 52 | ||
52 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 53 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
53 | /* | 54 | /* |
@@ -135,7 +136,11 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) | |||
135 | int i, index, len, enable; | 136 | int i, index, len, enable; |
136 | uint32_t ms; | 137 | uint32_t ms; |
137 | struct lpfc_debugfs_trc *dtp; | 138 | struct lpfc_debugfs_trc *dtp; |
138 | char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE]; | 139 | char *buffer; |
140 | |||
141 | buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL); | ||
142 | if (!buffer) | ||
143 | return 0; | ||
139 | 144 | ||
140 | enable = lpfc_debugfs_enable; | 145 | enable = lpfc_debugfs_enable; |
141 | lpfc_debugfs_enable = 0; | 146 | lpfc_debugfs_enable = 0; |
@@ -167,6 +172,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) | |||
167 | } | 172 | } |
168 | 173 | ||
169 | lpfc_debugfs_enable = enable; | 174 | lpfc_debugfs_enable = enable; |
175 | kfree(buffer); | ||
176 | |||
170 | return len; | 177 | return len; |
171 | } | 178 | } |
172 | 179 | ||
@@ -195,8 +202,11 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) | |||
195 | int i, index, len, enable; | 202 | int i, index, len, enable; |
196 | uint32_t ms; | 203 | uint32_t ms; |
197 | struct lpfc_debugfs_trc *dtp; | 204 | struct lpfc_debugfs_trc *dtp; |
198 | char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE]; | 205 | char *buffer; |
199 | 206 | ||
207 | buffer = kmalloc(LPFC_DEBUG_TRC_ENTRY_SIZE, GFP_KERNEL); | ||
208 | if (!buffer) | ||
209 | return 0; | ||
200 | 210 | ||
201 | enable = lpfc_debugfs_enable; | 211 | enable = lpfc_debugfs_enable; |
202 | lpfc_debugfs_enable = 0; | 212 | lpfc_debugfs_enable = 0; |
@@ -228,6 +238,8 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) | |||
228 | } | 238 | } |
229 | 239 | ||
230 | lpfc_debugfs_enable = enable; | 240 | lpfc_debugfs_enable = enable; |
241 | kfree(buffer); | ||
242 | |||
231 | return len; | 243 | return len; |
232 | } | 244 | } |
233 | 245 | ||
@@ -378,7 +390,11 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) | |||
378 | int len = 0; | 390 | int len = 0; |
379 | int i, off; | 391 | int i, off; |
380 | uint32_t *ptr; | 392 | uint32_t *ptr; |
381 | char buffer[1024]; | 393 | char *buffer; |
394 | |||
395 | buffer = kmalloc(1024, GFP_KERNEL); | ||
396 | if (!buffer) | ||
397 | return 0; | ||
382 | 398 | ||
383 | off = 0; | 399 | off = 0; |
384 | spin_lock_irq(&phba->hbalock); | 400 | spin_lock_irq(&phba->hbalock); |
@@ -407,6 +423,8 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) | |||
407 | } | 423 | } |
408 | 424 | ||
409 | spin_unlock_irq(&phba->hbalock); | 425 | spin_unlock_irq(&phba->hbalock); |
426 | kfree(buffer); | ||
427 | |||
410 | return len; | 428 | return len; |
411 | } | 429 | } |
412 | 430 | ||
@@ -1327,8 +1345,8 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, | |||
1327 | return 0; | 1345 | return 0; |
1328 | 1346 | ||
1329 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | 1347 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { |
1330 | where = idiag.cmd.data[0]; | 1348 | where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; |
1331 | count = idiag.cmd.data[1]; | 1349 | count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; |
1332 | } else | 1350 | } else |
1333 | return 0; | 1351 | return 0; |
1334 | 1352 | ||
@@ -1373,6 +1391,11 @@ pcicfg_browse: | |||
1373 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | 1391 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, |
1374 | "%08x ", u32val); | 1392 | "%08x ", u32val); |
1375 | offset += sizeof(uint32_t); | 1393 | offset += sizeof(uint32_t); |
1394 | if (offset >= LPFC_PCI_CFG_SIZE) { | ||
1395 | len += snprintf(pbuffer+len, | ||
1396 | LPFC_PCI_CFG_SIZE-len, "\n"); | ||
1397 | break; | ||
1398 | } | ||
1376 | index -= sizeof(uint32_t); | 1399 | index -= sizeof(uint32_t); |
1377 | if (!index) | 1400 | if (!index) |
1378 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | 1401 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, |
@@ -1385,8 +1408,11 @@ pcicfg_browse: | |||
1385 | } | 1408 | } |
1386 | 1409 | ||
1387 | /* Set up the offset for next portion of pci cfg read */ | 1410 | /* Set up the offset for next portion of pci cfg read */ |
1388 | idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE; | 1411 | if (index == 0) { |
1389 | if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE) | 1412 | idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE; |
1413 | if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE) | ||
1414 | idiag.offset.last_rd = 0; | ||
1415 | } else | ||
1390 | idiag.offset.last_rd = 0; | 1416 | idiag.offset.last_rd = 0; |
1391 | 1417 | ||
1392 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | 1418 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); |
@@ -1439,8 +1465,8 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | |||
1439 | if (rc != LPFC_PCI_CFG_RD_CMD_ARG) | 1465 | if (rc != LPFC_PCI_CFG_RD_CMD_ARG) |
1440 | goto error_out; | 1466 | goto error_out; |
1441 | /* Read command from PCI config space, set up command fields */ | 1467 | /* Read command from PCI config space, set up command fields */ |
1442 | where = idiag.cmd.data[0]; | 1468 | where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; |
1443 | count = idiag.cmd.data[1]; | 1469 | count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; |
1444 | if (count == LPFC_PCI_CFG_BROWSE) { | 1470 | if (count == LPFC_PCI_CFG_BROWSE) { |
1445 | if (where % sizeof(uint32_t)) | 1471 | if (where % sizeof(uint32_t)) |
1446 | goto error_out; | 1472 | goto error_out; |
@@ -1475,9 +1501,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | |||
1475 | if (rc != LPFC_PCI_CFG_WR_CMD_ARG) | 1501 | if (rc != LPFC_PCI_CFG_WR_CMD_ARG) |
1476 | goto error_out; | 1502 | goto error_out; |
1477 | /* Write command to PCI config space, read-modify-write */ | 1503 | /* Write command to PCI config space, read-modify-write */ |
1478 | where = idiag.cmd.data[0]; | 1504 | where = idiag.cmd.data[IDIAG_PCICFG_WHERE_INDX]; |
1479 | count = idiag.cmd.data[1]; | 1505 | count = idiag.cmd.data[IDIAG_PCICFG_COUNT_INDX]; |
1480 | value = idiag.cmd.data[2]; | 1506 | value = idiag.cmd.data[IDIAG_PCICFG_VALUE_INDX]; |
1481 | /* Sanity checks */ | 1507 | /* Sanity checks */ |
1482 | if ((count != sizeof(uint8_t)) && | 1508 | if ((count != sizeof(uint8_t)) && |
1483 | (count != sizeof(uint16_t)) && | 1509 | (count != sizeof(uint16_t)) && |
@@ -1570,6 +1596,292 @@ error_out: | |||
1570 | } | 1596 | } |
1571 | 1597 | ||
1572 | /** | 1598 | /** |
1599 | * lpfc_idiag_baracc_read - idiag debugfs pci bar access read | ||
1600 | * @file: The file pointer to read from. | ||
1601 | * @buf: The buffer to copy the data to. | ||
1602 | * @nbytes: The number of bytes to read. | ||
1603 | * @ppos: The position in the file to start reading from. | ||
1604 | * | ||
1605 | * Description: | ||
1606 | * This routine reads data from the @phba pci bar memory mapped space | ||
1607 | * according to the idiag command, and copies to user @buf. | ||
1608 | * | ||
1609 | * Returns: | ||
1610 | * This function returns the amount of data that was read (this could be less | ||
1611 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1612 | **/ | ||
1613 | static ssize_t | ||
1614 | lpfc_idiag_baracc_read(struct file *file, char __user *buf, size_t nbytes, | ||
1615 | loff_t *ppos) | ||
1616 | { | ||
1617 | struct lpfc_debug *debug = file->private_data; | ||
1618 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1619 | int offset_label, offset, offset_run, len = 0, index; | ||
1620 | int bar_num, acc_range, bar_size; | ||
1621 | char *pbuffer; | ||
1622 | void __iomem *mem_mapped_bar; | ||
1623 | uint32_t if_type; | ||
1624 | struct pci_dev *pdev; | ||
1625 | uint32_t u32val; | ||
1626 | |||
1627 | pdev = phba->pcidev; | ||
1628 | if (!pdev) | ||
1629 | return 0; | ||
1630 | |||
1631 | /* This is a user read operation */ | ||
1632 | debug->op = LPFC_IDIAG_OP_RD; | ||
1633 | |||
1634 | if (!debug->buffer) | ||
1635 | debug->buffer = kmalloc(LPFC_PCI_BAR_RD_BUF_SIZE, GFP_KERNEL); | ||
1636 | if (!debug->buffer) | ||
1637 | return 0; | ||
1638 | pbuffer = debug->buffer; | ||
1639 | |||
1640 | if (*ppos) | ||
1641 | return 0; | ||
1642 | |||
1643 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) { | ||
1644 | bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX]; | ||
1645 | offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX]; | ||
1646 | acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX]; | ||
1647 | bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX]; | ||
1648 | } else | ||
1649 | return 0; | ||
1650 | |||
1651 | if (acc_range == 0) | ||
1652 | return 0; | ||
1653 | |||
1654 | if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); | ||
1655 | if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { | ||
1656 | if (bar_num == IDIAG_BARACC_BAR_0) | ||
1657 | mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; | ||
1658 | else if (bar_num == IDIAG_BARACC_BAR_1) | ||
1659 | mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p; | ||
1660 | else if (bar_num == IDIAG_BARACC_BAR_2) | ||
1661 | mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p; | ||
1662 | else | ||
1663 | return 0; | ||
1664 | } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { | ||
1665 | if (bar_num == IDIAG_BARACC_BAR_0) | ||
1666 | mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; | ||
1667 | else | ||
1668 | return 0; | ||
1669 | } else | ||
1670 | return 0; | ||
1671 | |||
1672 | /* Read single PCI bar space register */ | ||
1673 | if (acc_range == SINGLE_WORD) { | ||
1674 | offset_run = offset; | ||
1675 | u32val = readl(mem_mapped_bar + offset_run); | ||
1676 | len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, | ||
1677 | "%05x: %08x\n", offset_run, u32val); | ||
1678 | } else | ||
1679 | goto baracc_browse; | ||
1680 | |||
1681 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1682 | |||
1683 | baracc_browse: | ||
1684 | |||
1685 | /* Browse all PCI bar space registers */ | ||
1686 | offset_label = idiag.offset.last_rd; | ||
1687 | offset_run = offset_label; | ||
1688 | |||
1689 | /* Read PCI bar memory mapped space */ | ||
1690 | len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, | ||
1691 | "%05x: ", offset_label); | ||
1692 | index = LPFC_PCI_BAR_RD_SIZE; | ||
1693 | while (index > 0) { | ||
1694 | u32val = readl(mem_mapped_bar + offset_run); | ||
1695 | len += snprintf(pbuffer+len, LPFC_PCI_BAR_RD_BUF_SIZE-len, | ||
1696 | "%08x ", u32val); | ||
1697 | offset_run += sizeof(uint32_t); | ||
1698 | if (acc_range == LPFC_PCI_BAR_BROWSE) { | ||
1699 | if (offset_run >= bar_size) { | ||
1700 | len += snprintf(pbuffer+len, | ||
1701 | LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); | ||
1702 | break; | ||
1703 | } | ||
1704 | } else { | ||
1705 | if (offset_run >= offset + | ||
1706 | (acc_range * sizeof(uint32_t))) { | ||
1707 | len += snprintf(pbuffer+len, | ||
1708 | LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); | ||
1709 | break; | ||
1710 | } | ||
1711 | } | ||
1712 | index -= sizeof(uint32_t); | ||
1713 | if (!index) | ||
1714 | len += snprintf(pbuffer+len, | ||
1715 | LPFC_PCI_BAR_RD_BUF_SIZE-len, "\n"); | ||
1716 | else if (!(index % (8 * sizeof(uint32_t)))) { | ||
1717 | offset_label += (8 * sizeof(uint32_t)); | ||
1718 | len += snprintf(pbuffer+len, | ||
1719 | LPFC_PCI_BAR_RD_BUF_SIZE-len, | ||
1720 | "\n%05x: ", offset_label); | ||
1721 | } | ||
1722 | } | ||
1723 | |||
1724 | /* Set up the offset for next portion of pci bar read */ | ||
1725 | if (index == 0) { | ||
1726 | idiag.offset.last_rd += LPFC_PCI_BAR_RD_SIZE; | ||
1727 | if (acc_range == LPFC_PCI_BAR_BROWSE) { | ||
1728 | if (idiag.offset.last_rd >= bar_size) | ||
1729 | idiag.offset.last_rd = 0; | ||
1730 | } else { | ||
1731 | if (offset_run >= offset + | ||
1732 | (acc_range * sizeof(uint32_t))) | ||
1733 | idiag.offset.last_rd = offset; | ||
1734 | } | ||
1735 | } else { | ||
1736 | if (acc_range == LPFC_PCI_BAR_BROWSE) | ||
1737 | idiag.offset.last_rd = 0; | ||
1738 | else | ||
1739 | idiag.offset.last_rd = offset; | ||
1740 | } | ||
1741 | |||
1742 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1743 | } | ||
1744 | |||
1745 | /** | ||
1746 | * lpfc_idiag_baracc_write - Syntax check and set up idiag bar access commands | ||
1747 | * @file: The file pointer to read from. | ||
1748 | * @buf: The buffer to copy the user data from. | ||
1749 | * @nbytes: The number of bytes to get. | ||
1750 | * @ppos: The position in the file to start reading from. | ||
1751 | * | ||
1752 | * This routine get the debugfs idiag command struct from user space and | ||
1753 | * then perform the syntax check for PCI bar memory mapped space read or | ||
1754 | * write command accordingly. In the case of PCI bar memory mapped space | ||
1755 | * read command, it sets up the command in the idiag command struct for | ||
1756 | * the debugfs read operation. In the case of PCI bar memorpy mapped space | ||
1757 | * write operation, it executes the write operation into the PCI bar memory | ||
1758 | * mapped space accordingly. | ||
1759 | * | ||
1760 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
1761 | * In case of error conditions, it returns proper error code back to the user | ||
1762 | * space. | ||
1763 | */ | ||
1764 | static ssize_t | ||
1765 | lpfc_idiag_baracc_write(struct file *file, const char __user *buf, | ||
1766 | size_t nbytes, loff_t *ppos) | ||
1767 | { | ||
1768 | struct lpfc_debug *debug = file->private_data; | ||
1769 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1770 | uint32_t bar_num, bar_size, offset, value, acc_range; | ||
1771 | struct pci_dev *pdev; | ||
1772 | void __iomem *mem_mapped_bar; | ||
1773 | uint32_t if_type; | ||
1774 | uint32_t u32val; | ||
1775 | int rc; | ||
1776 | |||
1777 | pdev = phba->pcidev; | ||
1778 | if (!pdev) | ||
1779 | return -EFAULT; | ||
1780 | |||
1781 | /* This is a user write operation */ | ||
1782 | debug->op = LPFC_IDIAG_OP_WR; | ||
1783 | |||
1784 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
1785 | if (rc < 0) | ||
1786 | return rc; | ||
1787 | |||
1788 | if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); | ||
1789 | bar_num = idiag.cmd.data[IDIAG_BARACC_BAR_NUM_INDX]; | ||
1790 | |||
1791 | if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { | ||
1792 | if ((bar_num != IDIAG_BARACC_BAR_0) && | ||
1793 | (bar_num != IDIAG_BARACC_BAR_1) && | ||
1794 | (bar_num != IDIAG_BARACC_BAR_2)) | ||
1795 | goto error_out; | ||
1796 | } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { | ||
1797 | if (bar_num != IDIAG_BARACC_BAR_0) | ||
1798 | goto error_out; | ||
1799 | } else | ||
1800 | goto error_out; | ||
1801 | |||
1802 | if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { | ||
1803 | if (bar_num == IDIAG_BARACC_BAR_0) { | ||
1804 | idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = | ||
1805 | LPFC_PCI_IF0_BAR0_SIZE; | ||
1806 | mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; | ||
1807 | } else if (bar_num == IDIAG_BARACC_BAR_1) { | ||
1808 | idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = | ||
1809 | LPFC_PCI_IF0_BAR1_SIZE; | ||
1810 | mem_mapped_bar = phba->sli4_hba.ctrl_regs_memmap_p; | ||
1811 | } else if (bar_num == IDIAG_BARACC_BAR_2) { | ||
1812 | idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = | ||
1813 | LPFC_PCI_IF0_BAR2_SIZE; | ||
1814 | mem_mapped_bar = phba->sli4_hba.drbl_regs_memmap_p; | ||
1815 | } else | ||
1816 | goto error_out; | ||
1817 | } else if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { | ||
1818 | if (bar_num == IDIAG_BARACC_BAR_0) { | ||
1819 | idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX] = | ||
1820 | LPFC_PCI_IF2_BAR0_SIZE; | ||
1821 | mem_mapped_bar = phba->sli4_hba.conf_regs_memmap_p; | ||
1822 | } else | ||
1823 | goto error_out; | ||
1824 | } else | ||
1825 | goto error_out; | ||
1826 | |||
1827 | offset = idiag.cmd.data[IDIAG_BARACC_OFF_SET_INDX]; | ||
1828 | if (offset % sizeof(uint32_t)) | ||
1829 | goto error_out; | ||
1830 | |||
1831 | bar_size = idiag.cmd.data[IDIAG_BARACC_BAR_SZE_INDX]; | ||
1832 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_RD) { | ||
1833 | /* Sanity check on PCI config read command line arguments */ | ||
1834 | if (rc != LPFC_PCI_BAR_RD_CMD_ARG) | ||
1835 | goto error_out; | ||
1836 | acc_range = idiag.cmd.data[IDIAG_BARACC_ACC_MOD_INDX]; | ||
1837 | if (acc_range == LPFC_PCI_BAR_BROWSE) { | ||
1838 | if (offset > bar_size - sizeof(uint32_t)) | ||
1839 | goto error_out; | ||
1840 | /* Starting offset to browse */ | ||
1841 | idiag.offset.last_rd = offset; | ||
1842 | } else if (acc_range > SINGLE_WORD) { | ||
1843 | if (offset + acc_range * sizeof(uint32_t) > bar_size) | ||
1844 | goto error_out; | ||
1845 | /* Starting offset to browse */ | ||
1846 | idiag.offset.last_rd = offset; | ||
1847 | } else if (acc_range != SINGLE_WORD) | ||
1848 | goto error_out; | ||
1849 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR || | ||
1850 | idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST || | ||
1851 | idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) { | ||
1852 | /* Sanity check on PCI bar write command line arguments */ | ||
1853 | if (rc != LPFC_PCI_BAR_WR_CMD_ARG) | ||
1854 | goto error_out; | ||
1855 | /* Write command to PCI bar space, read-modify-write */ | ||
1856 | acc_range = SINGLE_WORD; | ||
1857 | value = idiag.cmd.data[IDIAG_BARACC_REG_VAL_INDX]; | ||
1858 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_WR) { | ||
1859 | writel(value, mem_mapped_bar + offset); | ||
1860 | readl(mem_mapped_bar + offset); | ||
1861 | } | ||
1862 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_ST) { | ||
1863 | u32val = readl(mem_mapped_bar + offset); | ||
1864 | u32val |= value; | ||
1865 | writel(u32val, mem_mapped_bar + offset); | ||
1866 | readl(mem_mapped_bar + offset); | ||
1867 | } | ||
1868 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_BARACC_CL) { | ||
1869 | u32val = readl(mem_mapped_bar + offset); | ||
1870 | u32val &= ~value; | ||
1871 | writel(u32val, mem_mapped_bar + offset); | ||
1872 | readl(mem_mapped_bar + offset); | ||
1873 | } | ||
1874 | } else | ||
1875 | /* All other opecodes are illegal for now */ | ||
1876 | goto error_out; | ||
1877 | |||
1878 | return nbytes; | ||
1879 | error_out: | ||
1880 | memset(&idiag, 0, sizeof(idiag)); | ||
1881 | return -EINVAL; | ||
1882 | } | ||
1883 | |||
1884 | /** | ||
1573 | * lpfc_idiag_queinfo_read - idiag debugfs read queue information | 1885 | * lpfc_idiag_queinfo_read - idiag debugfs read queue information |
1574 | * @file: The file pointer to read from. | 1886 | * @file: The file pointer to read from. |
1575 | * @buf: The buffer to copy the data to. | 1887 | * @buf: The buffer to copy the data to. |
@@ -1871,8 +2183,8 @@ lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes, | |||
1871 | return 0; | 2183 | return 0; |
1872 | 2184 | ||
1873 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { | 2185 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { |
1874 | index = idiag.cmd.data[2]; | 2186 | index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX]; |
1875 | count = idiag.cmd.data[3]; | 2187 | count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX]; |
1876 | pque = (struct lpfc_queue *)idiag.ptr_private; | 2188 | pque = (struct lpfc_queue *)idiag.ptr_private; |
1877 | } else | 2189 | } else |
1878 | return 0; | 2190 | return 0; |
@@ -1944,12 +2256,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | |||
1944 | return rc; | 2256 | return rc; |
1945 | 2257 | ||
1946 | /* Get and sanity check on command feilds */ | 2258 | /* Get and sanity check on command feilds */ |
1947 | quetp = idiag.cmd.data[0]; | 2259 | quetp = idiag.cmd.data[IDIAG_QUEACC_QUETP_INDX]; |
1948 | queid = idiag.cmd.data[1]; | 2260 | queid = idiag.cmd.data[IDIAG_QUEACC_QUEID_INDX]; |
1949 | index = idiag.cmd.data[2]; | 2261 | index = idiag.cmd.data[IDIAG_QUEACC_INDEX_INDX]; |
1950 | count = idiag.cmd.data[3]; | 2262 | count = idiag.cmd.data[IDIAG_QUEACC_COUNT_INDX]; |
1951 | offset = idiag.cmd.data[4]; | 2263 | offset = idiag.cmd.data[IDIAG_QUEACC_OFFST_INDX]; |
1952 | value = idiag.cmd.data[5]; | 2264 | value = idiag.cmd.data[IDIAG_QUEACC_VALUE_INDX]; |
1953 | 2265 | ||
1954 | /* Sanity check on command line arguments */ | 2266 | /* Sanity check on command line arguments */ |
1955 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || | 2267 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || |
@@ -2218,7 +2530,7 @@ lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes, | |||
2218 | return 0; | 2530 | return 0; |
2219 | 2531 | ||
2220 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) | 2532 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) |
2221 | drb_reg_id = idiag.cmd.data[0]; | 2533 | drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX]; |
2222 | else | 2534 | else |
2223 | return 0; | 2535 | return 0; |
2224 | 2536 | ||
@@ -2257,7 +2569,7 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf, | |||
2257 | { | 2569 | { |
2258 | struct lpfc_debug *debug = file->private_data; | 2570 | struct lpfc_debug *debug = file->private_data; |
2259 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | 2571 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; |
2260 | uint32_t drb_reg_id, value, reg_val; | 2572 | uint32_t drb_reg_id, value, reg_val = 0; |
2261 | void __iomem *drb_reg; | 2573 | void __iomem *drb_reg; |
2262 | int rc; | 2574 | int rc; |
2263 | 2575 | ||
@@ -2269,8 +2581,8 @@ lpfc_idiag_drbacc_write(struct file *file, const char __user *buf, | |||
2269 | return rc; | 2581 | return rc; |
2270 | 2582 | ||
2271 | /* Sanity check on command line arguments */ | 2583 | /* Sanity check on command line arguments */ |
2272 | drb_reg_id = idiag.cmd.data[0]; | 2584 | drb_reg_id = idiag.cmd.data[IDIAG_DRBACC_REGID_INDX]; |
2273 | value = idiag.cmd.data[1]; | 2585 | value = idiag.cmd.data[IDIAG_DRBACC_VALUE_INDX]; |
2274 | 2586 | ||
2275 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || | 2587 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || |
2276 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || | 2588 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || |
@@ -2330,6 +2642,679 @@ error_out: | |||
2330 | return -EINVAL; | 2642 | return -EINVAL; |
2331 | } | 2643 | } |
2332 | 2644 | ||
2645 | /** | ||
2646 | * lpfc_idiag_ctlacc_read_reg - idiag debugfs read a control registers | ||
2647 | * @phba: The pointer to hba structure. | ||
2648 | * @pbuffer: The pointer to the buffer to copy the data to. | ||
2649 | * @len: The lenght of bytes to copied. | ||
2650 | * @drbregid: The id to doorbell registers. | ||
2651 | * | ||
2652 | * Description: | ||
2653 | * This routine reads a control register and copies its content to the | ||
2654 | * user buffer pointed to by @pbuffer. | ||
2655 | * | ||
2656 | * Returns: | ||
2657 | * This function returns the amount of data that was copied into @pbuffer. | ||
2658 | **/ | ||
2659 | static int | ||
2660 | lpfc_idiag_ctlacc_read_reg(struct lpfc_hba *phba, char *pbuffer, | ||
2661 | int len, uint32_t ctlregid) | ||
2662 | { | ||
2663 | |||
2664 | if (!pbuffer) | ||
2665 | return 0; | ||
2666 | |||
2667 | switch (ctlregid) { | ||
2668 | case LPFC_CTL_PORT_SEM: | ||
2669 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2670 | "Port SemReg: 0x%08x\n", | ||
2671 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2672 | LPFC_CTL_PORT_SEM_OFFSET)); | ||
2673 | break; | ||
2674 | case LPFC_CTL_PORT_STA: | ||
2675 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2676 | "Port StaReg: 0x%08x\n", | ||
2677 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2678 | LPFC_CTL_PORT_STA_OFFSET)); | ||
2679 | break; | ||
2680 | case LPFC_CTL_PORT_CTL: | ||
2681 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2682 | "Port CtlReg: 0x%08x\n", | ||
2683 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2684 | LPFC_CTL_PORT_CTL_OFFSET)); | ||
2685 | break; | ||
2686 | case LPFC_CTL_PORT_ER1: | ||
2687 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2688 | "Port Er1Reg: 0x%08x\n", | ||
2689 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2690 | LPFC_CTL_PORT_ER1_OFFSET)); | ||
2691 | break; | ||
2692 | case LPFC_CTL_PORT_ER2: | ||
2693 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2694 | "Port Er2Reg: 0x%08x\n", | ||
2695 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2696 | LPFC_CTL_PORT_ER2_OFFSET)); | ||
2697 | break; | ||
2698 | case LPFC_CTL_PDEV_CTL: | ||
2699 | len += snprintf(pbuffer+len, LPFC_CTL_ACC_BUF_SIZE-len, | ||
2700 | "PDev CtlReg: 0x%08x\n", | ||
2701 | readl(phba->sli4_hba.conf_regs_memmap_p + | ||
2702 | LPFC_CTL_PDEV_CTL_OFFSET)); | ||
2703 | break; | ||
2704 | default: | ||
2705 | break; | ||
2706 | } | ||
2707 | return len; | ||
2708 | } | ||
2709 | |||
2710 | /** | ||
2711 | * lpfc_idiag_ctlacc_read - idiag debugfs read port and device control register | ||
2712 | * @file: The file pointer to read from. | ||
2713 | * @buf: The buffer to copy the data to. | ||
2714 | * @nbytes: The number of bytes to read. | ||
2715 | * @ppos: The position in the file to start reading from. | ||
2716 | * | ||
2717 | * Description: | ||
2718 | * This routine reads data from the @phba port and device registers according | ||
2719 | * to the idiag command, and copies to user @buf. | ||
2720 | * | ||
2721 | * Returns: | ||
2722 | * This function returns the amount of data that was read (this could be less | ||
2723 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
2724 | **/ | ||
2725 | static ssize_t | ||
2726 | lpfc_idiag_ctlacc_read(struct file *file, char __user *buf, size_t nbytes, | ||
2727 | loff_t *ppos) | ||
2728 | { | ||
2729 | struct lpfc_debug *debug = file->private_data; | ||
2730 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
2731 | uint32_t ctl_reg_id, i; | ||
2732 | char *pbuffer; | ||
2733 | int len = 0; | ||
2734 | |||
2735 | /* This is a user read operation */ | ||
2736 | debug->op = LPFC_IDIAG_OP_RD; | ||
2737 | |||
2738 | if (!debug->buffer) | ||
2739 | debug->buffer = kmalloc(LPFC_CTL_ACC_BUF_SIZE, GFP_KERNEL); | ||
2740 | if (!debug->buffer) | ||
2741 | return 0; | ||
2742 | pbuffer = debug->buffer; | ||
2743 | |||
2744 | if (*ppos) | ||
2745 | return 0; | ||
2746 | |||
2747 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) | ||
2748 | ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX]; | ||
2749 | else | ||
2750 | return 0; | ||
2751 | |||
2752 | if (ctl_reg_id == LPFC_CTL_ACC_ALL) | ||
2753 | for (i = 1; i <= LPFC_CTL_MAX; i++) | ||
2754 | len = lpfc_idiag_ctlacc_read_reg(phba, | ||
2755 | pbuffer, len, i); | ||
2756 | else | ||
2757 | len = lpfc_idiag_ctlacc_read_reg(phba, | ||
2758 | pbuffer, len, ctl_reg_id); | ||
2759 | |||
2760 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
2761 | } | ||
2762 | |||
2763 | /** | ||
2764 | * lpfc_idiag_ctlacc_write - Syntax check and set up idiag ctlacc commands | ||
2765 | * @file: The file pointer to read from. | ||
2766 | * @buf: The buffer to copy the user data from. | ||
2767 | * @nbytes: The number of bytes to get. | ||
2768 | * @ppos: The position in the file to start reading from. | ||
2769 | * | ||
2770 | * This routine get the debugfs idiag command struct from user space and then | ||
2771 | * perform the syntax check for port and device control register read (dump) | ||
2772 | * or write (set) command accordingly. | ||
2773 | * | ||
2774 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
2775 | * In case of error conditions, it returns proper error code back to the user | ||
2776 | * space. | ||
2777 | **/ | ||
2778 | static ssize_t | ||
2779 | lpfc_idiag_ctlacc_write(struct file *file, const char __user *buf, | ||
2780 | size_t nbytes, loff_t *ppos) | ||
2781 | { | ||
2782 | struct lpfc_debug *debug = file->private_data; | ||
2783 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
2784 | uint32_t ctl_reg_id, value, reg_val = 0; | ||
2785 | void __iomem *ctl_reg; | ||
2786 | int rc; | ||
2787 | |||
2788 | /* This is a user write operation */ | ||
2789 | debug->op = LPFC_IDIAG_OP_WR; | ||
2790 | |||
2791 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
2792 | if (rc < 0) | ||
2793 | return rc; | ||
2794 | |||
2795 | /* Sanity check on command line arguments */ | ||
2796 | ctl_reg_id = idiag.cmd.data[IDIAG_CTLACC_REGID_INDX]; | ||
2797 | value = idiag.cmd.data[IDIAG_CTLACC_VALUE_INDX]; | ||
2798 | |||
2799 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR || | ||
2800 | idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST || | ||
2801 | idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { | ||
2802 | if (rc != LPFC_CTL_ACC_WR_CMD_ARG) | ||
2803 | goto error_out; | ||
2804 | if (ctl_reg_id > LPFC_CTL_MAX) | ||
2805 | goto error_out; | ||
2806 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_RD) { | ||
2807 | if (rc != LPFC_CTL_ACC_RD_CMD_ARG) | ||
2808 | goto error_out; | ||
2809 | if ((ctl_reg_id > LPFC_CTL_MAX) && | ||
2810 | (ctl_reg_id != LPFC_CTL_ACC_ALL)) | ||
2811 | goto error_out; | ||
2812 | } else | ||
2813 | goto error_out; | ||
2814 | |||
2815 | /* Perform the write access operation */ | ||
2816 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR || | ||
2817 | idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST || | ||
2818 | idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { | ||
2819 | switch (ctl_reg_id) { | ||
2820 | case LPFC_CTL_PORT_SEM: | ||
2821 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2822 | LPFC_CTL_PORT_SEM_OFFSET; | ||
2823 | break; | ||
2824 | case LPFC_CTL_PORT_STA: | ||
2825 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2826 | LPFC_CTL_PORT_STA_OFFSET; | ||
2827 | break; | ||
2828 | case LPFC_CTL_PORT_CTL: | ||
2829 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2830 | LPFC_CTL_PORT_CTL_OFFSET; | ||
2831 | break; | ||
2832 | case LPFC_CTL_PORT_ER1: | ||
2833 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2834 | LPFC_CTL_PORT_ER1_OFFSET; | ||
2835 | break; | ||
2836 | case LPFC_CTL_PORT_ER2: | ||
2837 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2838 | LPFC_CTL_PORT_ER2_OFFSET; | ||
2839 | break; | ||
2840 | case LPFC_CTL_PDEV_CTL: | ||
2841 | ctl_reg = phba->sli4_hba.conf_regs_memmap_p + | ||
2842 | LPFC_CTL_PDEV_CTL_OFFSET; | ||
2843 | break; | ||
2844 | default: | ||
2845 | goto error_out; | ||
2846 | } | ||
2847 | |||
2848 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_WR) | ||
2849 | reg_val = value; | ||
2850 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_ST) { | ||
2851 | reg_val = readl(ctl_reg); | ||
2852 | reg_val |= value; | ||
2853 | } | ||
2854 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_CTLACC_CL) { | ||
2855 | reg_val = readl(ctl_reg); | ||
2856 | reg_val &= ~value; | ||
2857 | } | ||
2858 | writel(reg_val, ctl_reg); | ||
2859 | readl(ctl_reg); /* flush */ | ||
2860 | } | ||
2861 | return nbytes; | ||
2862 | |||
2863 | error_out: | ||
2864 | /* Clean out command structure on command error out */ | ||
2865 | memset(&idiag, 0, sizeof(idiag)); | ||
2866 | return -EINVAL; | ||
2867 | } | ||
2868 | |||
2869 | /** | ||
2870 | * lpfc_idiag_mbxacc_get_setup - idiag debugfs get mailbox access setup | ||
2871 | * @phba: Pointer to HBA context object. | ||
2872 | * @pbuffer: Pointer to data buffer. | ||
2873 | * | ||
2874 | * Description: | ||
2875 | * This routine gets the driver mailbox access debugfs setup information. | ||
2876 | * | ||
2877 | * Returns: | ||
2878 | * This function returns the amount of data that was read (this could be less | ||
2879 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
2880 | **/ | ||
2881 | static int | ||
2882 | lpfc_idiag_mbxacc_get_setup(struct lpfc_hba *phba, char *pbuffer) | ||
2883 | { | ||
2884 | uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd; | ||
2885 | int len = 0; | ||
2886 | |||
2887 | mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; | ||
2888 | mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; | ||
2889 | mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; | ||
2890 | mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; | ||
2891 | |||
2892 | len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, | ||
2893 | "mbx_dump_map: 0x%08x\n", mbx_dump_map); | ||
2894 | len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, | ||
2895 | "mbx_dump_cnt: %04d\n", mbx_dump_cnt); | ||
2896 | len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, | ||
2897 | "mbx_word_cnt: %04d\n", mbx_word_cnt); | ||
2898 | len += snprintf(pbuffer+len, LPFC_MBX_ACC_BUF_SIZE-len, | ||
2899 | "mbx_mbox_cmd: 0x%02x\n", mbx_mbox_cmd); | ||
2900 | |||
2901 | return len; | ||
2902 | } | ||
2903 | |||
2904 | /** | ||
2905 | * lpfc_idiag_mbxacc_read - idiag debugfs read on mailbox access | ||
2906 | * @file: The file pointer to read from. | ||
2907 | * @buf: The buffer to copy the data to. | ||
2908 | * @nbytes: The number of bytes to read. | ||
2909 | * @ppos: The position in the file to start reading from. | ||
2910 | * | ||
2911 | * Description: | ||
2912 | * This routine reads data from the @phba driver mailbox access debugfs setup | ||
2913 | * information. | ||
2914 | * | ||
2915 | * Returns: | ||
2916 | * This function returns the amount of data that was read (this could be less | ||
2917 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
2918 | **/ | ||
2919 | static ssize_t | ||
2920 | lpfc_idiag_mbxacc_read(struct file *file, char __user *buf, size_t nbytes, | ||
2921 | loff_t *ppos) | ||
2922 | { | ||
2923 | struct lpfc_debug *debug = file->private_data; | ||
2924 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
2925 | char *pbuffer; | ||
2926 | int len = 0; | ||
2927 | |||
2928 | /* This is a user read operation */ | ||
2929 | debug->op = LPFC_IDIAG_OP_RD; | ||
2930 | |||
2931 | if (!debug->buffer) | ||
2932 | debug->buffer = kmalloc(LPFC_MBX_ACC_BUF_SIZE, GFP_KERNEL); | ||
2933 | if (!debug->buffer) | ||
2934 | return 0; | ||
2935 | pbuffer = debug->buffer; | ||
2936 | |||
2937 | if (*ppos) | ||
2938 | return 0; | ||
2939 | |||
2940 | if ((idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) && | ||
2941 | (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP)) | ||
2942 | return 0; | ||
2943 | |||
2944 | len = lpfc_idiag_mbxacc_get_setup(phba, pbuffer); | ||
2945 | |||
2946 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
2947 | } | ||
2948 | |||
2949 | /** | ||
2950 | * lpfc_idiag_mbxacc_write - Syntax check and set up idiag mbxacc commands | ||
2951 | * @file: The file pointer to read from. | ||
2952 | * @buf: The buffer to copy the user data from. | ||
2953 | * @nbytes: The number of bytes to get. | ||
2954 | * @ppos: The position in the file to start reading from. | ||
2955 | * | ||
2956 | * This routine get the debugfs idiag command struct from user space and then | ||
2957 | * perform the syntax check for driver mailbox command (dump) and sets up the | ||
2958 | * necessary states in the idiag command struct accordingly. | ||
2959 | * | ||
2960 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
2961 | * In case of error conditions, it returns proper error code back to the user | ||
2962 | * space. | ||
2963 | **/ | ||
2964 | static ssize_t | ||
2965 | lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf, | ||
2966 | size_t nbytes, loff_t *ppos) | ||
2967 | { | ||
2968 | struct lpfc_debug *debug = file->private_data; | ||
2969 | uint32_t mbx_dump_map, mbx_dump_cnt, mbx_word_cnt, mbx_mbox_cmd; | ||
2970 | int rc; | ||
2971 | |||
2972 | /* This is a user write operation */ | ||
2973 | debug->op = LPFC_IDIAG_OP_WR; | ||
2974 | |||
2975 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
2976 | if (rc < 0) | ||
2977 | return rc; | ||
2978 | |||
2979 | /* Sanity check on command line arguments */ | ||
2980 | mbx_mbox_cmd = idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; | ||
2981 | mbx_dump_map = idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; | ||
2982 | mbx_dump_cnt = idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; | ||
2983 | mbx_word_cnt = idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; | ||
2984 | |||
2985 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_MBXACC_DP) { | ||
2986 | if (!(mbx_dump_map & LPFC_MBX_DMP_MBX_ALL)) | ||
2987 | goto error_out; | ||
2988 | if ((mbx_dump_map & ~LPFC_MBX_DMP_MBX_ALL) && | ||
2989 | (mbx_dump_map != LPFC_MBX_DMP_ALL)) | ||
2990 | goto error_out; | ||
2991 | if (mbx_word_cnt > sizeof(MAILBOX_t)) | ||
2992 | goto error_out; | ||
2993 | } else if (idiag.cmd.opcode == LPFC_IDIAG_BSG_MBXACC_DP) { | ||
2994 | if (!(mbx_dump_map & LPFC_BSG_DMP_MBX_ALL)) | ||
2995 | goto error_out; | ||
2996 | if ((mbx_dump_map & ~LPFC_BSG_DMP_MBX_ALL) && | ||
2997 | (mbx_dump_map != LPFC_MBX_DMP_ALL)) | ||
2998 | goto error_out; | ||
2999 | if (mbx_word_cnt > (BSG_MBOX_SIZE)/4) | ||
3000 | goto error_out; | ||
3001 | if (mbx_mbox_cmd != 0x9b) | ||
3002 | goto error_out; | ||
3003 | } else | ||
3004 | goto error_out; | ||
3005 | |||
3006 | if (mbx_word_cnt == 0) | ||
3007 | goto error_out; | ||
3008 | if (rc != LPFC_MBX_DMP_ARG) | ||
3009 | goto error_out; | ||
3010 | if (mbx_mbox_cmd & ~0xff) | ||
3011 | goto error_out; | ||
3012 | |||
3013 | /* condition for stop mailbox dump */ | ||
3014 | if (mbx_dump_cnt == 0) | ||
3015 | goto reset_out; | ||
3016 | |||
3017 | return nbytes; | ||
3018 | |||
3019 | reset_out: | ||
3020 | /* Clean out command structure on command error out */ | ||
3021 | memset(&idiag, 0, sizeof(idiag)); | ||
3022 | return nbytes; | ||
3023 | |||
3024 | error_out: | ||
3025 | /* Clean out command structure on command error out */ | ||
3026 | memset(&idiag, 0, sizeof(idiag)); | ||
3027 | return -EINVAL; | ||
3028 | } | ||
3029 | |||
3030 | /** | ||
3031 | * lpfc_idiag_extacc_avail_get - get the available extents information | ||
3032 | * @phba: pointer to lpfc hba data structure. | ||
3033 | * @pbuffer: pointer to internal buffer. | ||
3034 | * @len: length into the internal buffer data has been copied. | ||
3035 | * | ||
3036 | * Description: | ||
3037 | * This routine is to get the available extent information. | ||
3038 | * | ||
3039 | * Returns: | ||
3040 | * overall lenth of the data read into the internal buffer. | ||
3041 | **/ | ||
3042 | static int | ||
3043 | lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len) | ||
3044 | { | ||
3045 | uint16_t ext_cnt, ext_size; | ||
3046 | |||
3047 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3048 | "\nAvailable Extents Information:\n"); | ||
3049 | |||
3050 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3051 | "\tPort Available VPI extents: "); | ||
3052 | lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VPI, | ||
3053 | &ext_cnt, &ext_size); | ||
3054 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3055 | "Count %3d, Size %3d\n", ext_cnt, ext_size); | ||
3056 | |||
3057 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3058 | "\tPort Available VFI extents: "); | ||
3059 | lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_VFI, | ||
3060 | &ext_cnt, &ext_size); | ||
3061 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3062 | "Count %3d, Size %3d\n", ext_cnt, ext_size); | ||
3063 | |||
3064 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3065 | "\tPort Available RPI extents: "); | ||
3066 | lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_RPI, | ||
3067 | &ext_cnt, &ext_size); | ||
3068 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3069 | "Count %3d, Size %3d\n", ext_cnt, ext_size); | ||
3070 | |||
3071 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3072 | "\tPort Available XRI extents: "); | ||
3073 | lpfc_sli4_get_avail_extnt_rsrc(phba, LPFC_RSC_TYPE_FCOE_XRI, | ||
3074 | &ext_cnt, &ext_size); | ||
3075 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3076 | "Count %3d, Size %3d\n", ext_cnt, ext_size); | ||
3077 | |||
3078 | return len; | ||
3079 | } | ||
3080 | |||
3081 | /** | ||
3082 | * lpfc_idiag_extacc_alloc_get - get the allocated extents information | ||
3083 | * @phba: pointer to lpfc hba data structure. | ||
3084 | * @pbuffer: pointer to internal buffer. | ||
3085 | * @len: length into the internal buffer data has been copied. | ||
3086 | * | ||
3087 | * Description: | ||
3088 | * This routine is to get the allocated extent information. | ||
3089 | * | ||
3090 | * Returns: | ||
3091 | * overall lenth of the data read into the internal buffer. | ||
3092 | **/ | ||
3093 | static int | ||
3094 | lpfc_idiag_extacc_alloc_get(struct lpfc_hba *phba, char *pbuffer, int len) | ||
3095 | { | ||
3096 | uint16_t ext_cnt, ext_size; | ||
3097 | int rc; | ||
3098 | |||
3099 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3100 | "\nAllocated Extents Information:\n"); | ||
3101 | |||
3102 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3103 | "\tHost Allocated VPI extents: "); | ||
3104 | rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VPI, | ||
3105 | &ext_cnt, &ext_size); | ||
3106 | if (!rc) | ||
3107 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3108 | "Port %d Extent %3d, Size %3d\n", | ||
3109 | phba->brd_no, ext_cnt, ext_size); | ||
3110 | else | ||
3111 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3112 | "N/A\n"); | ||
3113 | |||
3114 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3115 | "\tHost Allocated VFI extents: "); | ||
3116 | rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_VFI, | ||
3117 | &ext_cnt, &ext_size); | ||
3118 | if (!rc) | ||
3119 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3120 | "Port %d Extent %3d, Size %3d\n", | ||
3121 | phba->brd_no, ext_cnt, ext_size); | ||
3122 | else | ||
3123 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3124 | "N/A\n"); | ||
3125 | |||
3126 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3127 | "\tHost Allocated RPI extents: "); | ||
3128 | rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_RPI, | ||
3129 | &ext_cnt, &ext_size); | ||
3130 | if (!rc) | ||
3131 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3132 | "Port %d Extent %3d, Size %3d\n", | ||
3133 | phba->brd_no, ext_cnt, ext_size); | ||
3134 | else | ||
3135 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3136 | "N/A\n"); | ||
3137 | |||
3138 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3139 | "\tHost Allocated XRI extents: "); | ||
3140 | rc = lpfc_sli4_get_allocated_extnts(phba, LPFC_RSC_TYPE_FCOE_XRI, | ||
3141 | &ext_cnt, &ext_size); | ||
3142 | if (!rc) | ||
3143 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3144 | "Port %d Extent %3d, Size %3d\n", | ||
3145 | phba->brd_no, ext_cnt, ext_size); | ||
3146 | else | ||
3147 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3148 | "N/A\n"); | ||
3149 | |||
3150 | return len; | ||
3151 | } | ||
3152 | |||
3153 | /** | ||
3154 | * lpfc_idiag_extacc_drivr_get - get driver extent information | ||
3155 | * @phba: pointer to lpfc hba data structure. | ||
3156 | * @pbuffer: pointer to internal buffer. | ||
3157 | * @len: length into the internal buffer data has been copied. | ||
3158 | * | ||
3159 | * Description: | ||
3160 | * This routine is to get the driver extent information. | ||
3161 | * | ||
3162 | * Returns: | ||
3163 | * overall lenth of the data read into the internal buffer. | ||
3164 | **/ | ||
3165 | static int | ||
3166 | lpfc_idiag_extacc_drivr_get(struct lpfc_hba *phba, char *pbuffer, int len) | ||
3167 | { | ||
3168 | struct lpfc_rsrc_blks *rsrc_blks; | ||
3169 | int index; | ||
3170 | |||
3171 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3172 | "\nDriver Extents Information:\n"); | ||
3173 | |||
3174 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3175 | "\tVPI extents:\n"); | ||
3176 | index = 0; | ||
3177 | list_for_each_entry(rsrc_blks, &phba->lpfc_vpi_blk_list, list) { | ||
3178 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3179 | "\t\tBlock %3d: Start %4d, Count %4d\n", | ||
3180 | index, rsrc_blks->rsrc_start, | ||
3181 | rsrc_blks->rsrc_size); | ||
3182 | index++; | ||
3183 | } | ||
3184 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3185 | "\tVFI extents:\n"); | ||
3186 | index = 0; | ||
3187 | list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_vfi_blk_list, | ||
3188 | list) { | ||
3189 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3190 | "\t\tBlock %3d: Start %4d, Count %4d\n", | ||
3191 | index, rsrc_blks->rsrc_start, | ||
3192 | rsrc_blks->rsrc_size); | ||
3193 | index++; | ||
3194 | } | ||
3195 | |||
3196 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3197 | "\tRPI extents:\n"); | ||
3198 | index = 0; | ||
3199 | list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_rpi_blk_list, | ||
3200 | list) { | ||
3201 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3202 | "\t\tBlock %3d: Start %4d, Count %4d\n", | ||
3203 | index, rsrc_blks->rsrc_start, | ||
3204 | rsrc_blks->rsrc_size); | ||
3205 | index++; | ||
3206 | } | ||
3207 | |||
3208 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3209 | "\tXRI extents:\n"); | ||
3210 | index = 0; | ||
3211 | list_for_each_entry(rsrc_blks, &phba->sli4_hba.lpfc_xri_blk_list, | ||
3212 | list) { | ||
3213 | len += snprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, | ||
3214 | "\t\tBlock %3d: Start %4d, Count %4d\n", | ||
3215 | index, rsrc_blks->rsrc_start, | ||
3216 | rsrc_blks->rsrc_size); | ||
3217 | index++; | ||
3218 | } | ||
3219 | |||
3220 | return len; | ||
3221 | } | ||
3222 | |||
3223 | /** | ||
3224 | * lpfc_idiag_extacc_write - Syntax check and set up idiag extacc commands | ||
3225 | * @file: The file pointer to read from. | ||
3226 | * @buf: The buffer to copy the user data from. | ||
3227 | * @nbytes: The number of bytes to get. | ||
3228 | * @ppos: The position in the file to start reading from. | ||
3229 | * | ||
3230 | * This routine get the debugfs idiag command struct from user space and then | ||
3231 | * perform the syntax check for extent information access commands and sets | ||
3232 | * up the necessary states in the idiag command struct accordingly. | ||
3233 | * | ||
3234 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
3235 | * In case of error conditions, it returns proper error code back to the user | ||
3236 | * space. | ||
3237 | **/ | ||
3238 | static ssize_t | ||
3239 | lpfc_idiag_extacc_write(struct file *file, const char __user *buf, | ||
3240 | size_t nbytes, loff_t *ppos) | ||
3241 | { | ||
3242 | struct lpfc_debug *debug = file->private_data; | ||
3243 | uint32_t ext_map; | ||
3244 | int rc; | ||
3245 | |||
3246 | /* This is a user write operation */ | ||
3247 | debug->op = LPFC_IDIAG_OP_WR; | ||
3248 | |||
3249 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
3250 | if (rc < 0) | ||
3251 | return rc; | ||
3252 | |||
3253 | ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX]; | ||
3254 | |||
3255 | if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD) | ||
3256 | goto error_out; | ||
3257 | if (rc != LPFC_EXT_ACC_CMD_ARG) | ||
3258 | goto error_out; | ||
3259 | if (!(ext_map & LPFC_EXT_ACC_ALL)) | ||
3260 | goto error_out; | ||
3261 | |||
3262 | return nbytes; | ||
3263 | error_out: | ||
3264 | /* Clean out command structure on command error out */ | ||
3265 | memset(&idiag, 0, sizeof(idiag)); | ||
3266 | return -EINVAL; | ||
3267 | } | ||
3268 | |||
3269 | /** | ||
3270 | * lpfc_idiag_extacc_read - idiag debugfs read access to extent information | ||
3271 | * @file: The file pointer to read from. | ||
3272 | * @buf: The buffer to copy the data to. | ||
3273 | * @nbytes: The number of bytes to read. | ||
3274 | * @ppos: The position in the file to start reading from. | ||
3275 | * | ||
3276 | * Description: | ||
3277 | * This routine reads data from the proper extent information according to | ||
3278 | * the idiag command, and copies to user @buf. | ||
3279 | * | ||
3280 | * Returns: | ||
3281 | * This function returns the amount of data that was read (this could be less | ||
3282 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
3283 | **/ | ||
3284 | static ssize_t | ||
3285 | lpfc_idiag_extacc_read(struct file *file, char __user *buf, size_t nbytes, | ||
3286 | loff_t *ppos) | ||
3287 | { | ||
3288 | struct lpfc_debug *debug = file->private_data; | ||
3289 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
3290 | char *pbuffer; | ||
3291 | uint32_t ext_map; | ||
3292 | int len = 0; | ||
3293 | |||
3294 | /* This is a user read operation */ | ||
3295 | debug->op = LPFC_IDIAG_OP_RD; | ||
3296 | |||
3297 | if (!debug->buffer) | ||
3298 | debug->buffer = kmalloc(LPFC_EXT_ACC_BUF_SIZE, GFP_KERNEL); | ||
3299 | if (!debug->buffer) | ||
3300 | return 0; | ||
3301 | pbuffer = debug->buffer; | ||
3302 | if (*ppos) | ||
3303 | return 0; | ||
3304 | if (idiag.cmd.opcode != LPFC_IDIAG_CMD_EXTACC_RD) | ||
3305 | return 0; | ||
3306 | |||
3307 | ext_map = idiag.cmd.data[IDIAG_EXTACC_EXMAP_INDX]; | ||
3308 | if (ext_map & LPFC_EXT_ACC_AVAIL) | ||
3309 | len = lpfc_idiag_extacc_avail_get(phba, pbuffer, len); | ||
3310 | if (ext_map & LPFC_EXT_ACC_ALLOC) | ||
3311 | len = lpfc_idiag_extacc_alloc_get(phba, pbuffer, len); | ||
3312 | if (ext_map & LPFC_EXT_ACC_DRIVR) | ||
3313 | len = lpfc_idiag_extacc_drivr_get(phba, pbuffer, len); | ||
3314 | |||
3315 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
3316 | } | ||
3317 | |||
2333 | #undef lpfc_debugfs_op_disc_trc | 3318 | #undef lpfc_debugfs_op_disc_trc |
2334 | static const struct file_operations lpfc_debugfs_op_disc_trc = { | 3319 | static const struct file_operations lpfc_debugfs_op_disc_trc = { |
2335 | .owner = THIS_MODULE, | 3320 | .owner = THIS_MODULE, |
@@ -2420,6 +3405,16 @@ static const struct file_operations lpfc_idiag_op_pciCfg = { | |||
2420 | .release = lpfc_idiag_cmd_release, | 3405 | .release = lpfc_idiag_cmd_release, |
2421 | }; | 3406 | }; |
2422 | 3407 | ||
3408 | #undef lpfc_idiag_op_barAcc | ||
3409 | static const struct file_operations lpfc_idiag_op_barAcc = { | ||
3410 | .owner = THIS_MODULE, | ||
3411 | .open = lpfc_idiag_open, | ||
3412 | .llseek = lpfc_debugfs_lseek, | ||
3413 | .read = lpfc_idiag_baracc_read, | ||
3414 | .write = lpfc_idiag_baracc_write, | ||
3415 | .release = lpfc_idiag_cmd_release, | ||
3416 | }; | ||
3417 | |||
2423 | #undef lpfc_idiag_op_queInfo | 3418 | #undef lpfc_idiag_op_queInfo |
2424 | static const struct file_operations lpfc_idiag_op_queInfo = { | 3419 | static const struct file_operations lpfc_idiag_op_queInfo = { |
2425 | .owner = THIS_MODULE, | 3420 | .owner = THIS_MODULE, |
@@ -2428,7 +3423,7 @@ static const struct file_operations lpfc_idiag_op_queInfo = { | |||
2428 | .release = lpfc_idiag_release, | 3423 | .release = lpfc_idiag_release, |
2429 | }; | 3424 | }; |
2430 | 3425 | ||
2431 | #undef lpfc_idiag_op_queacc | 3426 | #undef lpfc_idiag_op_queAcc |
2432 | static const struct file_operations lpfc_idiag_op_queAcc = { | 3427 | static const struct file_operations lpfc_idiag_op_queAcc = { |
2433 | .owner = THIS_MODULE, | 3428 | .owner = THIS_MODULE, |
2434 | .open = lpfc_idiag_open, | 3429 | .open = lpfc_idiag_open, |
@@ -2438,7 +3433,7 @@ static const struct file_operations lpfc_idiag_op_queAcc = { | |||
2438 | .release = lpfc_idiag_cmd_release, | 3433 | .release = lpfc_idiag_cmd_release, |
2439 | }; | 3434 | }; |
2440 | 3435 | ||
2441 | #undef lpfc_idiag_op_drbacc | 3436 | #undef lpfc_idiag_op_drbAcc |
2442 | static const struct file_operations lpfc_idiag_op_drbAcc = { | 3437 | static const struct file_operations lpfc_idiag_op_drbAcc = { |
2443 | .owner = THIS_MODULE, | 3438 | .owner = THIS_MODULE, |
2444 | .open = lpfc_idiag_open, | 3439 | .open = lpfc_idiag_open, |
@@ -2448,8 +3443,234 @@ static const struct file_operations lpfc_idiag_op_drbAcc = { | |||
2448 | .release = lpfc_idiag_cmd_release, | 3443 | .release = lpfc_idiag_cmd_release, |
2449 | }; | 3444 | }; |
2450 | 3445 | ||
3446 | #undef lpfc_idiag_op_ctlAcc | ||
3447 | static const struct file_operations lpfc_idiag_op_ctlAcc = { | ||
3448 | .owner = THIS_MODULE, | ||
3449 | .open = lpfc_idiag_open, | ||
3450 | .llseek = lpfc_debugfs_lseek, | ||
3451 | .read = lpfc_idiag_ctlacc_read, | ||
3452 | .write = lpfc_idiag_ctlacc_write, | ||
3453 | .release = lpfc_idiag_cmd_release, | ||
3454 | }; | ||
3455 | |||
3456 | #undef lpfc_idiag_op_mbxAcc | ||
3457 | static const struct file_operations lpfc_idiag_op_mbxAcc = { | ||
3458 | .owner = THIS_MODULE, | ||
3459 | .open = lpfc_idiag_open, | ||
3460 | .llseek = lpfc_debugfs_lseek, | ||
3461 | .read = lpfc_idiag_mbxacc_read, | ||
3462 | .write = lpfc_idiag_mbxacc_write, | ||
3463 | .release = lpfc_idiag_cmd_release, | ||
3464 | }; | ||
3465 | |||
3466 | #undef lpfc_idiag_op_extAcc | ||
3467 | static const struct file_operations lpfc_idiag_op_extAcc = { | ||
3468 | .owner = THIS_MODULE, | ||
3469 | .open = lpfc_idiag_open, | ||
3470 | .llseek = lpfc_debugfs_lseek, | ||
3471 | .read = lpfc_idiag_extacc_read, | ||
3472 | .write = lpfc_idiag_extacc_write, | ||
3473 | .release = lpfc_idiag_cmd_release, | ||
3474 | }; | ||
3475 | |||
2451 | #endif | 3476 | #endif |
2452 | 3477 | ||
3478 | /* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command | ||
3479 | * @phba: Pointer to HBA context object. | ||
3480 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
3481 | * | ||
3482 | * Description: | ||
3483 | * This routine dump a bsg pass-through non-embedded mailbox command with | ||
3484 | * external buffer. | ||
3485 | **/ | ||
3486 | void | ||
3487 | lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *phba, enum nemb_type nemb_tp, | ||
3488 | enum mbox_type mbox_tp, enum dma_type dma_tp, | ||
3489 | enum sta_type sta_tp, | ||
3490 | struct lpfc_dmabuf *dmabuf, uint32_t ext_buf) | ||
3491 | { | ||
3492 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | ||
3493 | uint32_t *mbx_mbox_cmd, *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt; | ||
3494 | char line_buf[LPFC_MBX_ACC_LBUF_SZ]; | ||
3495 | int len = 0; | ||
3496 | uint32_t do_dump = 0; | ||
3497 | uint32_t *pword; | ||
3498 | uint32_t i; | ||
3499 | |||
3500 | if (idiag.cmd.opcode != LPFC_IDIAG_BSG_MBXACC_DP) | ||
3501 | return; | ||
3502 | |||
3503 | mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; | ||
3504 | mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; | ||
3505 | mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; | ||
3506 | mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; | ||
3507 | |||
3508 | if (!(*mbx_dump_map & LPFC_MBX_DMP_ALL) || | ||
3509 | (*mbx_dump_cnt == 0) || | ||
3510 | (*mbx_word_cnt == 0)) | ||
3511 | return; | ||
3512 | |||
3513 | if (*mbx_mbox_cmd != 0x9B) | ||
3514 | return; | ||
3515 | |||
3516 | if ((mbox_tp == mbox_rd) && (dma_tp == dma_mbox)) { | ||
3517 | if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_MBX) { | ||
3518 | do_dump |= LPFC_BSG_DMP_MBX_RD_MBX; | ||
3519 | printk(KERN_ERR "\nRead mbox command (x%x), " | ||
3520 | "nemb:0x%x, extbuf_cnt:%d:\n", | ||
3521 | sta_tp, nemb_tp, ext_buf); | ||
3522 | } | ||
3523 | } | ||
3524 | if ((mbox_tp == mbox_rd) && (dma_tp == dma_ebuf)) { | ||
3525 | if (*mbx_dump_map & LPFC_BSG_DMP_MBX_RD_BUF) { | ||
3526 | do_dump |= LPFC_BSG_DMP_MBX_RD_BUF; | ||
3527 | printk(KERN_ERR "\nRead mbox buffer (x%x), " | ||
3528 | "nemb:0x%x, extbuf_seq:%d:\n", | ||
3529 | sta_tp, nemb_tp, ext_buf); | ||
3530 | } | ||
3531 | } | ||
3532 | if ((mbox_tp == mbox_wr) && (dma_tp == dma_mbox)) { | ||
3533 | if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_MBX) { | ||
3534 | do_dump |= LPFC_BSG_DMP_MBX_WR_MBX; | ||
3535 | printk(KERN_ERR "\nWrite mbox command (x%x), " | ||
3536 | "nemb:0x%x, extbuf_cnt:%d:\n", | ||
3537 | sta_tp, nemb_tp, ext_buf); | ||
3538 | } | ||
3539 | } | ||
3540 | if ((mbox_tp == mbox_wr) && (dma_tp == dma_ebuf)) { | ||
3541 | if (*mbx_dump_map & LPFC_BSG_DMP_MBX_WR_BUF) { | ||
3542 | do_dump |= LPFC_BSG_DMP_MBX_WR_BUF; | ||
3543 | printk(KERN_ERR "\nWrite mbox buffer (x%x), " | ||
3544 | "nemb:0x%x, extbuf_seq:%d:\n", | ||
3545 | sta_tp, nemb_tp, ext_buf); | ||
3546 | } | ||
3547 | } | ||
3548 | |||
3549 | /* dump buffer content */ | ||
3550 | if (do_dump) { | ||
3551 | pword = (uint32_t *)dmabuf->virt; | ||
3552 | for (i = 0; i < *mbx_word_cnt; i++) { | ||
3553 | if (!(i % 8)) { | ||
3554 | if (i != 0) | ||
3555 | printk(KERN_ERR "%s\n", line_buf); | ||
3556 | len = 0; | ||
3557 | len += snprintf(line_buf+len, | ||
3558 | LPFC_MBX_ACC_LBUF_SZ-len, | ||
3559 | "%03d: ", i); | ||
3560 | } | ||
3561 | len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, | ||
3562 | "%08x ", (uint32_t)*pword); | ||
3563 | pword++; | ||
3564 | } | ||
3565 | if ((i - 1) % 8) | ||
3566 | printk(KERN_ERR "%s\n", line_buf); | ||
3567 | (*mbx_dump_cnt)--; | ||
3568 | } | ||
3569 | |||
3570 | /* Clean out command structure on reaching dump count */ | ||
3571 | if (*mbx_dump_cnt == 0) | ||
3572 | memset(&idiag, 0, sizeof(idiag)); | ||
3573 | return; | ||
3574 | #endif | ||
3575 | } | ||
3576 | |||
3577 | /* lpfc_idiag_mbxacc_dump_issue_mbox - idiag debugfs dump issue mailbox command | ||
3578 | * @phba: Pointer to HBA context object. | ||
3579 | * @dmabuf: Pointer to a DMA buffer descriptor. | ||
3580 | * | ||
3581 | * Description: | ||
3582 | * This routine dump a pass-through non-embedded mailbox command from issue | ||
3583 | * mailbox command. | ||
3584 | **/ | ||
3585 | void | ||
3586 | lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *phba, MAILBOX_t *pmbox) | ||
3587 | { | ||
3588 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | ||
3589 | uint32_t *mbx_dump_map, *mbx_dump_cnt, *mbx_word_cnt, *mbx_mbox_cmd; | ||
3590 | char line_buf[LPFC_MBX_ACC_LBUF_SZ]; | ||
3591 | int len = 0; | ||
3592 | uint32_t *pword; | ||
3593 | uint8_t *pbyte; | ||
3594 | uint32_t i, j; | ||
3595 | |||
3596 | if (idiag.cmd.opcode != LPFC_IDIAG_CMD_MBXACC_DP) | ||
3597 | return; | ||
3598 | |||
3599 | mbx_mbox_cmd = &idiag.cmd.data[IDIAG_MBXACC_MBCMD_INDX]; | ||
3600 | mbx_dump_map = &idiag.cmd.data[IDIAG_MBXACC_DPMAP_INDX]; | ||
3601 | mbx_dump_cnt = &idiag.cmd.data[IDIAG_MBXACC_DPCNT_INDX]; | ||
3602 | mbx_word_cnt = &idiag.cmd.data[IDIAG_MBXACC_WDCNT_INDX]; | ||
3603 | |||
3604 | if (!(*mbx_dump_map & LPFC_MBX_DMP_MBX_ALL) || | ||
3605 | (*mbx_dump_cnt == 0) || | ||
3606 | (*mbx_word_cnt == 0)) | ||
3607 | return; | ||
3608 | |||
3609 | if ((*mbx_mbox_cmd != LPFC_MBX_ALL_CMD) && | ||
3610 | (*mbx_mbox_cmd != pmbox->mbxCommand)) | ||
3611 | return; | ||
3612 | |||
3613 | /* dump buffer content */ | ||
3614 | if (*mbx_dump_map & LPFC_MBX_DMP_MBX_WORD) { | ||
3615 | printk(KERN_ERR "Mailbox command:0x%x dump by word:\n", | ||
3616 | pmbox->mbxCommand); | ||
3617 | pword = (uint32_t *)pmbox; | ||
3618 | for (i = 0; i < *mbx_word_cnt; i++) { | ||
3619 | if (!(i % 8)) { | ||
3620 | if (i != 0) | ||
3621 | printk(KERN_ERR "%s\n", line_buf); | ||
3622 | len = 0; | ||
3623 | memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); | ||
3624 | len += snprintf(line_buf+len, | ||
3625 | LPFC_MBX_ACC_LBUF_SZ-len, | ||
3626 | "%03d: ", i); | ||
3627 | } | ||
3628 | len += snprintf(line_buf+len, LPFC_MBX_ACC_LBUF_SZ-len, | ||
3629 | "%08x ", | ||
3630 | ((uint32_t)*pword) & 0xffffffff); | ||
3631 | pword++; | ||
3632 | } | ||
3633 | if ((i - 1) % 8) | ||
3634 | printk(KERN_ERR "%s\n", line_buf); | ||
3635 | printk(KERN_ERR "\n"); | ||
3636 | } | ||
3637 | if (*mbx_dump_map & LPFC_MBX_DMP_MBX_BYTE) { | ||
3638 | printk(KERN_ERR "Mailbox command:0x%x dump by byte:\n", | ||
3639 | pmbox->mbxCommand); | ||
3640 | pbyte = (uint8_t *)pmbox; | ||
3641 | for (i = 0; i < *mbx_word_cnt; i++) { | ||
3642 | if (!(i % 8)) { | ||
3643 | if (i != 0) | ||
3644 | printk(KERN_ERR "%s\n", line_buf); | ||
3645 | len = 0; | ||
3646 | memset(line_buf, 0, LPFC_MBX_ACC_LBUF_SZ); | ||
3647 | len += snprintf(line_buf+len, | ||
3648 | LPFC_MBX_ACC_LBUF_SZ-len, | ||
3649 | "%03d: ", i); | ||
3650 | } | ||
3651 | for (j = 0; j < 4; j++) { | ||
3652 | len += snprintf(line_buf+len, | ||
3653 | LPFC_MBX_ACC_LBUF_SZ-len, | ||
3654 | "%02x", | ||
3655 | ((uint8_t)*pbyte) & 0xff); | ||
3656 | pbyte++; | ||
3657 | } | ||
3658 | len += snprintf(line_buf+len, | ||
3659 | LPFC_MBX_ACC_LBUF_SZ-len, " "); | ||
3660 | } | ||
3661 | if ((i - 1) % 8) | ||
3662 | printk(KERN_ERR "%s\n", line_buf); | ||
3663 | printk(KERN_ERR "\n"); | ||
3664 | } | ||
3665 | (*mbx_dump_cnt)--; | ||
3666 | |||
3667 | /* Clean out command structure on reaching dump count */ | ||
3668 | if (*mbx_dump_cnt == 0) | ||
3669 | memset(&idiag, 0, sizeof(idiag)); | ||
3670 | return; | ||
3671 | #endif | ||
3672 | } | ||
3673 | |||
2453 | /** | 3674 | /** |
2454 | * lpfc_debugfs_initialize - Initialize debugfs for a vport | 3675 | * lpfc_debugfs_initialize - Initialize debugfs for a vport |
2455 | * @vport: The vport pointer to initialize. | 3676 | * @vport: The vport pointer to initialize. |
@@ -2673,7 +3894,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
2673 | vport, &lpfc_debugfs_op_nodelist); | 3894 | vport, &lpfc_debugfs_op_nodelist); |
2674 | if (!vport->debug_nodelist) { | 3895 | if (!vport->debug_nodelist) { |
2675 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 3896 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
2676 | "0409 Can't create debugfs nodelist\n"); | 3897 | "2985 Can't create debugfs nodelist\n"); |
2677 | goto debug_failed; | 3898 | goto debug_failed; |
2678 | } | 3899 | } |
2679 | 3900 | ||
@@ -2710,6 +3931,20 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
2710 | idiag.offset.last_rd = 0; | 3931 | idiag.offset.last_rd = 0; |
2711 | } | 3932 | } |
2712 | 3933 | ||
3934 | /* iDiag PCI BAR access */ | ||
3935 | snprintf(name, sizeof(name), "barAcc"); | ||
3936 | if (!phba->idiag_bar_acc) { | ||
3937 | phba->idiag_bar_acc = | ||
3938 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
3939 | phba->idiag_root, phba, &lpfc_idiag_op_barAcc); | ||
3940 | if (!phba->idiag_bar_acc) { | ||
3941 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
3942 | "3056 Can't create idiag debugfs\n"); | ||
3943 | goto debug_failed; | ||
3944 | } | ||
3945 | idiag.offset.last_rd = 0; | ||
3946 | } | ||
3947 | |||
2713 | /* iDiag get PCI function queue information */ | 3948 | /* iDiag get PCI function queue information */ |
2714 | snprintf(name, sizeof(name), "queInfo"); | 3949 | snprintf(name, sizeof(name), "queInfo"); |
2715 | if (!phba->idiag_que_info) { | 3950 | if (!phba->idiag_que_info) { |
@@ -2749,6 +3984,50 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
2749 | } | 3984 | } |
2750 | } | 3985 | } |
2751 | 3986 | ||
3987 | /* iDiag access PCI function control registers */ | ||
3988 | snprintf(name, sizeof(name), "ctlAcc"); | ||
3989 | if (!phba->idiag_ctl_acc) { | ||
3990 | phba->idiag_ctl_acc = | ||
3991 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
3992 | phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc); | ||
3993 | if (!phba->idiag_ctl_acc) { | ||
3994 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
3995 | "2981 Can't create idiag debugfs\n"); | ||
3996 | goto debug_failed; | ||
3997 | } | ||
3998 | } | ||
3999 | |||
4000 | /* iDiag access mbox commands */ | ||
4001 | snprintf(name, sizeof(name), "mbxAcc"); | ||
4002 | if (!phba->idiag_mbx_acc) { | ||
4003 | phba->idiag_mbx_acc = | ||
4004 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
4005 | phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc); | ||
4006 | if (!phba->idiag_mbx_acc) { | ||
4007 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
4008 | "2980 Can't create idiag debugfs\n"); | ||
4009 | goto debug_failed; | ||
4010 | } | ||
4011 | } | ||
4012 | |||
4013 | /* iDiag extents access commands */ | ||
4014 | if (phba->sli4_hba.extents_in_use) { | ||
4015 | snprintf(name, sizeof(name), "extAcc"); | ||
4016 | if (!phba->idiag_ext_acc) { | ||
4017 | phba->idiag_ext_acc = | ||
4018 | debugfs_create_file(name, | ||
4019 | S_IFREG|S_IRUGO|S_IWUSR, | ||
4020 | phba->idiag_root, phba, | ||
4021 | &lpfc_idiag_op_extAcc); | ||
4022 | if (!phba->idiag_ext_acc) { | ||
4023 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
4024 | "2986 Cant create " | ||
4025 | "idiag debugfs\n"); | ||
4026 | goto debug_failed; | ||
4027 | } | ||
4028 | } | ||
4029 | } | ||
4030 | |||
2752 | debug_failed: | 4031 | debug_failed: |
2753 | return; | 4032 | return; |
2754 | #endif | 4033 | #endif |
@@ -2783,7 +4062,6 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
2783 | debugfs_remove(vport->debug_nodelist); /* nodelist */ | 4062 | debugfs_remove(vport->debug_nodelist); /* nodelist */ |
2784 | vport->debug_nodelist = NULL; | 4063 | vport->debug_nodelist = NULL; |
2785 | } | 4064 | } |
2786 | |||
2787 | if (vport->vport_debugfs_root) { | 4065 | if (vport->vport_debugfs_root) { |
2788 | debugfs_remove(vport->vport_debugfs_root); /* vportX */ | 4066 | debugfs_remove(vport->vport_debugfs_root); /* vportX */ |
2789 | vport->vport_debugfs_root = NULL; | 4067 | vport->vport_debugfs_root = NULL; |
@@ -2827,6 +4105,21 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
2827 | * iDiag release | 4105 | * iDiag release |
2828 | */ | 4106 | */ |
2829 | if (phba->sli_rev == LPFC_SLI_REV4) { | 4107 | if (phba->sli_rev == LPFC_SLI_REV4) { |
4108 | if (phba->idiag_ext_acc) { | ||
4109 | /* iDiag extAcc */ | ||
4110 | debugfs_remove(phba->idiag_ext_acc); | ||
4111 | phba->idiag_ext_acc = NULL; | ||
4112 | } | ||
4113 | if (phba->idiag_mbx_acc) { | ||
4114 | /* iDiag mbxAcc */ | ||
4115 | debugfs_remove(phba->idiag_mbx_acc); | ||
4116 | phba->idiag_mbx_acc = NULL; | ||
4117 | } | ||
4118 | if (phba->idiag_ctl_acc) { | ||
4119 | /* iDiag ctlAcc */ | ||
4120 | debugfs_remove(phba->idiag_ctl_acc); | ||
4121 | phba->idiag_ctl_acc = NULL; | ||
4122 | } | ||
2830 | if (phba->idiag_drb_acc) { | 4123 | if (phba->idiag_drb_acc) { |
2831 | /* iDiag drbAcc */ | 4124 | /* iDiag drbAcc */ |
2832 | debugfs_remove(phba->idiag_drb_acc); | 4125 | debugfs_remove(phba->idiag_drb_acc); |
@@ -2842,6 +4135,11 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
2842 | debugfs_remove(phba->idiag_que_info); | 4135 | debugfs_remove(phba->idiag_que_info); |
2843 | phba->idiag_que_info = NULL; | 4136 | phba->idiag_que_info = NULL; |
2844 | } | 4137 | } |
4138 | if (phba->idiag_bar_acc) { | ||
4139 | /* iDiag barAcc */ | ||
4140 | debugfs_remove(phba->idiag_bar_acc); | ||
4141 | phba->idiag_bar_acc = NULL; | ||
4142 | } | ||
2845 | if (phba->idiag_pci_cfg) { | 4143 | if (phba->idiag_pci_cfg) { |
2846 | /* iDiag pciCfg */ | 4144 | /* iDiag pciCfg */ |
2847 | debugfs_remove(phba->idiag_pci_cfg); | 4145 | debugfs_remove(phba->idiag_pci_cfg); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 6525a5e62d27..f83bd944edd8 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h | |||
@@ -39,14 +39,51 @@ | |||
39 | /* hbqinfo output buffer size */ | 39 | /* hbqinfo output buffer size */ |
40 | #define LPFC_HBQINFO_SIZE 8192 | 40 | #define LPFC_HBQINFO_SIZE 8192 |
41 | 41 | ||
42 | /* | ||
43 | * For SLI4 iDiag debugfs diagnostics tool | ||
44 | */ | ||
45 | |||
42 | /* pciConf */ | 46 | /* pciConf */ |
43 | #define LPFC_PCI_CFG_BROWSE 0xffff | 47 | #define LPFC_PCI_CFG_BROWSE 0xffff |
44 | #define LPFC_PCI_CFG_RD_CMD_ARG 2 | 48 | #define LPFC_PCI_CFG_RD_CMD_ARG 2 |
45 | #define LPFC_PCI_CFG_WR_CMD_ARG 3 | 49 | #define LPFC_PCI_CFG_WR_CMD_ARG 3 |
46 | #define LPFC_PCI_CFG_SIZE 4096 | 50 | #define LPFC_PCI_CFG_SIZE 4096 |
47 | #define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) | ||
48 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) | 51 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) |
49 | 52 | ||
53 | #define IDIAG_PCICFG_WHERE_INDX 0 | ||
54 | #define IDIAG_PCICFG_COUNT_INDX 1 | ||
55 | #define IDIAG_PCICFG_VALUE_INDX 2 | ||
56 | |||
57 | /* barAcc */ | ||
58 | #define LPFC_PCI_BAR_BROWSE 0xffff | ||
59 | #define LPFC_PCI_BAR_RD_CMD_ARG 3 | ||
60 | #define LPFC_PCI_BAR_WR_CMD_ARG 3 | ||
61 | |||
62 | #define LPFC_PCI_IF0_BAR0_SIZE (1024 * 16) | ||
63 | #define LPFC_PCI_IF0_BAR1_SIZE (1024 * 128) | ||
64 | #define LPFC_PCI_IF0_BAR2_SIZE (1024 * 128) | ||
65 | #define LPFC_PCI_IF2_BAR0_SIZE (1024 * 32) | ||
66 | |||
67 | #define LPFC_PCI_BAR_RD_BUF_SIZE 4096 | ||
68 | #define LPFC_PCI_BAR_RD_SIZE (LPFC_PCI_BAR_RD_BUF_SIZE/4) | ||
69 | |||
70 | #define LPFC_PCI_IF0_BAR0_RD_SIZE (LPFC_PCI_IF0_BAR0_SIZE/4) | ||
71 | #define LPFC_PCI_IF0_BAR1_RD_SIZE (LPFC_PCI_IF0_BAR1_SIZE/4) | ||
72 | #define LPFC_PCI_IF0_BAR2_RD_SIZE (LPFC_PCI_IF0_BAR2_SIZE/4) | ||
73 | #define LPFC_PCI_IF2_BAR0_RD_SIZE (LPFC_PCI_IF2_BAR0_SIZE/4) | ||
74 | |||
75 | #define IDIAG_BARACC_BAR_NUM_INDX 0 | ||
76 | #define IDIAG_BARACC_OFF_SET_INDX 1 | ||
77 | #define IDIAG_BARACC_ACC_MOD_INDX 2 | ||
78 | #define IDIAG_BARACC_REG_VAL_INDX 2 | ||
79 | #define IDIAG_BARACC_BAR_SZE_INDX 3 | ||
80 | |||
81 | #define IDIAG_BARACC_BAR_0 0 | ||
82 | #define IDIAG_BARACC_BAR_1 1 | ||
83 | #define IDIAG_BARACC_BAR_2 2 | ||
84 | |||
85 | #define SINGLE_WORD 1 | ||
86 | |||
50 | /* queue info */ | 87 | /* queue info */ |
51 | #define LPFC_QUE_INFO_GET_BUF_SIZE 4096 | 88 | #define LPFC_QUE_INFO_GET_BUF_SIZE 4096 |
52 | 89 | ||
@@ -63,7 +100,14 @@ | |||
63 | #define LPFC_IDIAG_WQ 4 | 100 | #define LPFC_IDIAG_WQ 4 |
64 | #define LPFC_IDIAG_RQ 5 | 101 | #define LPFC_IDIAG_RQ 5 |
65 | 102 | ||
66 | /* doorbell acc */ | 103 | #define IDIAG_QUEACC_QUETP_INDX 0 |
104 | #define IDIAG_QUEACC_QUEID_INDX 1 | ||
105 | #define IDIAG_QUEACC_INDEX_INDX 2 | ||
106 | #define IDIAG_QUEACC_COUNT_INDX 3 | ||
107 | #define IDIAG_QUEACC_OFFST_INDX 4 | ||
108 | #define IDIAG_QUEACC_VALUE_INDX 5 | ||
109 | |||
110 | /* doorbell register acc */ | ||
67 | #define LPFC_DRB_ACC_ALL 0xffff | 111 | #define LPFC_DRB_ACC_ALL 0xffff |
68 | #define LPFC_DRB_ACC_RD_CMD_ARG 1 | 112 | #define LPFC_DRB_ACC_RD_CMD_ARG 1 |
69 | #define LPFC_DRB_ACC_WR_CMD_ARG 2 | 113 | #define LPFC_DRB_ACC_WR_CMD_ARG 2 |
@@ -76,6 +120,67 @@ | |||
76 | 120 | ||
77 | #define LPFC_DRB_MAX 4 | 121 | #define LPFC_DRB_MAX 4 |
78 | 122 | ||
123 | #define IDIAG_DRBACC_REGID_INDX 0 | ||
124 | #define IDIAG_DRBACC_VALUE_INDX 1 | ||
125 | |||
126 | /* control register acc */ | ||
127 | #define LPFC_CTL_ACC_ALL 0xffff | ||
128 | #define LPFC_CTL_ACC_RD_CMD_ARG 1 | ||
129 | #define LPFC_CTL_ACC_WR_CMD_ARG 2 | ||
130 | #define LPFC_CTL_ACC_BUF_SIZE 256 | ||
131 | |||
132 | #define LPFC_CTL_PORT_SEM 1 | ||
133 | #define LPFC_CTL_PORT_STA 2 | ||
134 | #define LPFC_CTL_PORT_CTL 3 | ||
135 | #define LPFC_CTL_PORT_ER1 4 | ||
136 | #define LPFC_CTL_PORT_ER2 5 | ||
137 | #define LPFC_CTL_PDEV_CTL 6 | ||
138 | |||
139 | #define LPFC_CTL_MAX 6 | ||
140 | |||
141 | #define IDIAG_CTLACC_REGID_INDX 0 | ||
142 | #define IDIAG_CTLACC_VALUE_INDX 1 | ||
143 | |||
144 | /* mailbox access */ | ||
145 | #define LPFC_MBX_DMP_ARG 4 | ||
146 | |||
147 | #define LPFC_MBX_ACC_BUF_SIZE 512 | ||
148 | #define LPFC_MBX_ACC_LBUF_SZ 128 | ||
149 | |||
150 | #define LPFC_MBX_DMP_MBX_WORD 0x00000001 | ||
151 | #define LPFC_MBX_DMP_MBX_BYTE 0x00000002 | ||
152 | #define LPFC_MBX_DMP_MBX_ALL (LPFC_MBX_DMP_MBX_WORD | LPFC_MBX_DMP_MBX_BYTE) | ||
153 | |||
154 | #define LPFC_BSG_DMP_MBX_RD_MBX 0x00000001 | ||
155 | #define LPFC_BSG_DMP_MBX_RD_BUF 0x00000002 | ||
156 | #define LPFC_BSG_DMP_MBX_WR_MBX 0x00000004 | ||
157 | #define LPFC_BSG_DMP_MBX_WR_BUF 0x00000008 | ||
158 | #define LPFC_BSG_DMP_MBX_ALL (LPFC_BSG_DMP_MBX_RD_MBX | \ | ||
159 | LPFC_BSG_DMP_MBX_RD_BUF | \ | ||
160 | LPFC_BSG_DMP_MBX_WR_MBX | \ | ||
161 | LPFC_BSG_DMP_MBX_WR_BUF) | ||
162 | |||
163 | #define LPFC_MBX_DMP_ALL 0xffff | ||
164 | #define LPFC_MBX_ALL_CMD 0xff | ||
165 | |||
166 | #define IDIAG_MBXACC_MBCMD_INDX 0 | ||
167 | #define IDIAG_MBXACC_DPMAP_INDX 1 | ||
168 | #define IDIAG_MBXACC_DPCNT_INDX 2 | ||
169 | #define IDIAG_MBXACC_WDCNT_INDX 3 | ||
170 | |||
171 | /* extents access */ | ||
172 | #define LPFC_EXT_ACC_CMD_ARG 1 | ||
173 | #define LPFC_EXT_ACC_BUF_SIZE 4096 | ||
174 | |||
175 | #define LPFC_EXT_ACC_AVAIL 0x1 | ||
176 | #define LPFC_EXT_ACC_ALLOC 0x2 | ||
177 | #define LPFC_EXT_ACC_DRIVR 0x4 | ||
178 | #define LPFC_EXT_ACC_ALL (LPFC_EXT_ACC_DRIVR | \ | ||
179 | LPFC_EXT_ACC_AVAIL | \ | ||
180 | LPFC_EXT_ACC_ALLOC) | ||
181 | |||
182 | #define IDIAG_EXTACC_EXMAP_INDX 0 | ||
183 | |||
79 | #define SIZE_U8 sizeof(uint8_t) | 184 | #define SIZE_U8 sizeof(uint8_t) |
80 | #define SIZE_U16 sizeof(uint16_t) | 185 | #define SIZE_U16 sizeof(uint16_t) |
81 | #define SIZE_U32 sizeof(uint32_t) | 186 | #define SIZE_U32 sizeof(uint32_t) |
@@ -110,6 +215,11 @@ struct lpfc_idiag_cmd { | |||
110 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 | 215 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 |
111 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 | 216 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 |
112 | 217 | ||
218 | #define LPFC_IDIAG_CMD_BARACC_RD 0x00000008 | ||
219 | #define LPFC_IDIAG_CMD_BARACC_WR 0x00000009 | ||
220 | #define LPFC_IDIAG_CMD_BARACC_ST 0x0000000a | ||
221 | #define LPFC_IDIAG_CMD_BARACC_CL 0x0000000b | ||
222 | |||
113 | #define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011 | 223 | #define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011 |
114 | #define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012 | 224 | #define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012 |
115 | #define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013 | 225 | #define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013 |
@@ -119,6 +229,17 @@ struct lpfc_idiag_cmd { | |||
119 | #define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022 | 229 | #define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022 |
120 | #define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023 | 230 | #define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023 |
121 | #define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024 | 231 | #define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024 |
232 | |||
233 | #define LPFC_IDIAG_CMD_CTLACC_RD 0x00000031 | ||
234 | #define LPFC_IDIAG_CMD_CTLACC_WR 0x00000032 | ||
235 | #define LPFC_IDIAG_CMD_CTLACC_ST 0x00000033 | ||
236 | #define LPFC_IDIAG_CMD_CTLACC_CL 0x00000034 | ||
237 | |||
238 | #define LPFC_IDIAG_CMD_MBXACC_DP 0x00000041 | ||
239 | #define LPFC_IDIAG_BSG_MBXACC_DP 0x00000042 | ||
240 | |||
241 | #define LPFC_IDIAG_CMD_EXTACC_RD 0x00000051 | ||
242 | |||
122 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; | 243 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; |
123 | }; | 244 | }; |
124 | 245 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 027b797c9916..4c58402fa698 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -9153,7 +9153,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
9153 | 9153 | ||
9154 | /* Check if there are static vports to be created. */ | 9154 | /* Check if there are static vports to be created. */ |
9155 | lpfc_create_static_vport(phba); | 9155 | lpfc_create_static_vport(phba); |
9156 | |||
9157 | return 0; | 9156 | return 0; |
9158 | 9157 | ||
9159 | out_disable_intr: | 9158 | out_disable_intr: |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5b28ea1d72c5..247c24f438f5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4714,10 +4714,15 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) | |||
4714 | * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count. | 4714 | * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count. |
4715 | * @phba: Pointer to HBA context object. | 4715 | * @phba: Pointer to HBA context object. |
4716 | * @type: The resource extent type. | 4716 | * @type: The resource extent type. |
4717 | * @extnt_count: buffer to hold port available extent count. | ||
4718 | * @extnt_size: buffer to hold element count per extent. | ||
4717 | * | 4719 | * |
4718 | * This function allocates all SLI4 resource identifiers. | 4720 | * This function calls the port and retrievs the number of available |
4721 | * extents and their size for a particular extent type. | ||
4722 | * | ||
4723 | * Returns: 0 if successful. Nonzero otherwise. | ||
4719 | **/ | 4724 | **/ |
4720 | static int | 4725 | int |
4721 | lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, | 4726 | lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, |
4722 | uint16_t *extnt_count, uint16_t *extnt_size) | 4727 | uint16_t *extnt_count, uint16_t *extnt_size) |
4723 | { | 4728 | { |
@@ -4894,7 +4899,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt, | |||
4894 | req_len, *emb); | 4899 | req_len, *emb); |
4895 | if (alloc_len < req_len) { | 4900 | if (alloc_len < req_len) { |
4896 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 4901 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
4897 | "9000 Allocated DMA memory size (x%x) is " | 4902 | "2982 Allocated DMA memory size (x%x) is " |
4898 | "less than the requested DMA memory " | 4903 | "less than the requested DMA memory " |
4899 | "size (x%x)\n", alloc_len, req_len); | 4904 | "size (x%x)\n", alloc_len, req_len); |
4900 | return -ENOMEM; | 4905 | return -ENOMEM; |
@@ -5508,6 +5513,154 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) | |||
5508 | } | 5513 | } |
5509 | 5514 | ||
5510 | /** | 5515 | /** |
5516 | * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents. | ||
5517 | * @phba: Pointer to HBA context object. | ||
5518 | * @type: The resource extent type. | ||
5519 | * @extnt_count: buffer to hold port extent count response | ||
5520 | * @extnt_size: buffer to hold port extent size response. | ||
5521 | * | ||
5522 | * This function calls the port to read the host allocated extents | ||
5523 | * for a particular type. | ||
5524 | **/ | ||
5525 | int | ||
5526 | lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, | ||
5527 | uint16_t *extnt_cnt, uint16_t *extnt_size) | ||
5528 | { | ||
5529 | bool emb; | ||
5530 | int rc = 0; | ||
5531 | uint16_t curr_blks = 0; | ||
5532 | uint32_t req_len, emb_len; | ||
5533 | uint32_t alloc_len, mbox_tmo; | ||
5534 | struct list_head *blk_list_head; | ||
5535 | struct lpfc_rsrc_blks *rsrc_blk; | ||
5536 | LPFC_MBOXQ_t *mbox; | ||
5537 | void *virtaddr = NULL; | ||
5538 | struct lpfc_mbx_nembed_rsrc_extent *n_rsrc; | ||
5539 | struct lpfc_mbx_alloc_rsrc_extents *rsrc_ext; | ||
5540 | union lpfc_sli4_cfg_shdr *shdr; | ||
5541 | |||
5542 | switch (type) { | ||
5543 | case LPFC_RSC_TYPE_FCOE_VPI: | ||
5544 | blk_list_head = &phba->lpfc_vpi_blk_list; | ||
5545 | break; | ||
5546 | case LPFC_RSC_TYPE_FCOE_XRI: | ||
5547 | blk_list_head = &phba->sli4_hba.lpfc_xri_blk_list; | ||
5548 | break; | ||
5549 | case LPFC_RSC_TYPE_FCOE_VFI: | ||
5550 | blk_list_head = &phba->sli4_hba.lpfc_vfi_blk_list; | ||
5551 | break; | ||
5552 | case LPFC_RSC_TYPE_FCOE_RPI: | ||
5553 | blk_list_head = &phba->sli4_hba.lpfc_rpi_blk_list; | ||
5554 | break; | ||
5555 | default: | ||
5556 | return -EIO; | ||
5557 | } | ||
5558 | |||
5559 | /* Count the number of extents currently allocatd for this type. */ | ||
5560 | list_for_each_entry(rsrc_blk, blk_list_head, list) { | ||
5561 | if (curr_blks == 0) { | ||
5562 | /* | ||
5563 | * The GET_ALLOCATED mailbox does not return the size, | ||
5564 | * just the count. The size should be just the size | ||
5565 | * stored in the current allocated block and all sizes | ||
5566 | * for an extent type are the same so set the return | ||
5567 | * value now. | ||
5568 | */ | ||
5569 | *extnt_size = rsrc_blk->rsrc_size; | ||
5570 | } | ||
5571 | curr_blks++; | ||
5572 | } | ||
5573 | |||
5574 | /* Calculate the total requested length of the dma memory. */ | ||
5575 | req_len = curr_blks * sizeof(uint16_t); | ||
5576 | |||
5577 | /* | ||
5578 | * Calculate the size of an embedded mailbox. The uint32_t | ||
5579 | * accounts for extents-specific word. | ||
5580 | */ | ||
5581 | emb_len = sizeof(MAILBOX_t) - sizeof(struct mbox_header) - | ||
5582 | sizeof(uint32_t); | ||
5583 | |||
5584 | /* | ||
5585 | * Presume the allocation and response will fit into an embedded | ||
5586 | * mailbox. If not true, reconfigure to a non-embedded mailbox. | ||
5587 | */ | ||
5588 | emb = LPFC_SLI4_MBX_EMBED; | ||
5589 | req_len = emb_len; | ||
5590 | if (req_len > emb_len) { | ||
5591 | req_len = curr_blks * sizeof(uint16_t) + | ||
5592 | sizeof(union lpfc_sli4_cfg_shdr) + | ||
5593 | sizeof(uint32_t); | ||
5594 | emb = LPFC_SLI4_MBX_NEMBED; | ||
5595 | } | ||
5596 | |||
5597 | mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
5598 | if (!mbox) | ||
5599 | return -ENOMEM; | ||
5600 | memset(mbox, 0, sizeof(LPFC_MBOXQ_t)); | ||
5601 | |||
5602 | alloc_len = lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
5603 | LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT, | ||
5604 | req_len, emb); | ||
5605 | if (alloc_len < req_len) { | ||
5606 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
5607 | "2983 Allocated DMA memory size (x%x) is " | ||
5608 | "less than the requested DMA memory " | ||
5609 | "size (x%x)\n", alloc_len, req_len); | ||
5610 | rc = -ENOMEM; | ||
5611 | goto err_exit; | ||
5612 | } | ||
5613 | rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, curr_blks, type, emb); | ||
5614 | if (unlikely(rc)) { | ||
5615 | rc = -EIO; | ||
5616 | goto err_exit; | ||
5617 | } | ||
5618 | |||
5619 | if (!phba->sli4_hba.intr_enable) | ||
5620 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL); | ||
5621 | else { | ||
5622 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
5623 | rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo); | ||
5624 | } | ||
5625 | |||
5626 | if (unlikely(rc)) { | ||
5627 | rc = -EIO; | ||
5628 | goto err_exit; | ||
5629 | } | ||
5630 | |||
5631 | /* | ||
5632 | * Figure out where the response is located. Then get local pointers | ||
5633 | * to the response data. The port does not guarantee to respond to | ||
5634 | * all extents counts request so update the local variable with the | ||
5635 | * allocated count from the port. | ||
5636 | */ | ||
5637 | if (emb == LPFC_SLI4_MBX_EMBED) { | ||
5638 | rsrc_ext = &mbox->u.mqe.un.alloc_rsrc_extents; | ||
5639 | shdr = &rsrc_ext->header.cfg_shdr; | ||
5640 | *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, &rsrc_ext->u.rsp); | ||
5641 | } else { | ||
5642 | virtaddr = mbox->sge_array->addr[0]; | ||
5643 | n_rsrc = (struct lpfc_mbx_nembed_rsrc_extent *) virtaddr; | ||
5644 | shdr = &n_rsrc->cfg_shdr; | ||
5645 | *extnt_cnt = bf_get(lpfc_mbx_rsrc_cnt, n_rsrc); | ||
5646 | } | ||
5647 | |||
5648 | if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) { | ||
5649 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT, | ||
5650 | "2984 Failed to read allocated resources " | ||
5651 | "for type %d - Status 0x%x Add'l Status 0x%x.\n", | ||
5652 | type, | ||
5653 | bf_get(lpfc_mbox_hdr_status, &shdr->response), | ||
5654 | bf_get(lpfc_mbox_hdr_add_status, &shdr->response)); | ||
5655 | rc = -EIO; | ||
5656 | goto err_exit; | ||
5657 | } | ||
5658 | err_exit: | ||
5659 | lpfc_sli4_mbox_cmd_free(phba, mbox); | ||
5660 | return rc; | ||
5661 | } | ||
5662 | |||
5663 | /** | ||
5511 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function | 5664 | * lpfc_sli4_hba_setup - SLI4 device intialization PCI function |
5512 | * @phba: Pointer to HBA context object. | 5665 | * @phba: Pointer to HBA context object. |
5513 | * | 5666 | * |
@@ -6637,6 +6790,9 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, | |||
6637 | unsigned long iflags; | 6790 | unsigned long iflags; |
6638 | int rc; | 6791 | int rc; |
6639 | 6792 | ||
6793 | /* dump from issue mailbox command if setup */ | ||
6794 | lpfc_idiag_mbxacc_dump_issue_mbox(phba, &mboxq->u.mb); | ||
6795 | |||
6640 | rc = lpfc_mbox_dev_check(phba); | 6796 | rc = lpfc_mbox_dev_check(phba); |
6641 | if (unlikely(rc)) { | 6797 | if (unlikely(rc)) { |
6642 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 6798 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |