aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-07-22 18:37:42 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-27 07:14:00 -0400
commitb76f2dc91c0fff7a66616affdc039dc2e4b7ff98 (patch)
treec918b99e5e368f32118044a3ecbb4e793443028c /drivers/scsi/lpfc
parent0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25 (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.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c37
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c1354
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.h125
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c162
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
810lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) 810lpfc_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. */
372int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *); 372int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *);
373int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *); 373int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *);
374int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t,
375 uint16_t *, uint16_t *);
376int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t,
377 uint16_t *, uint16_t *);
374 378
375/* externs BlockGuard */ 379/* externs BlockGuard */
376extern char *_dump_buf_data; 380extern char *_dump_buf_data;
@@ -437,6 +441,10 @@ void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
437void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *); 441void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
438struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, 442struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
439 uint32_t); 443 uint32_t);
444void 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);
447void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *);
440int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); 448int 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 */
442int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); 450int 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 **/
1613static ssize_t
1614lpfc_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
1683baracc_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 */
1764static ssize_t
1765lpfc_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;
1879error_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 **/
2659static int
2660lpfc_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 **/
2725static ssize_t
2726lpfc_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 **/
2778static ssize_t
2779lpfc_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
2863error_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 **/
2881static int
2882lpfc_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 **/
2919static ssize_t
2920lpfc_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 **/
2964static ssize_t
2965lpfc_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
3019reset_out:
3020 /* Clean out command structure on command error out */
3021 memset(&idiag, 0, sizeof(idiag));
3022 return nbytes;
3023
3024error_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 **/
3042static int
3043lpfc_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 **/
3093static int
3094lpfc_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 **/
3165static int
3166lpfc_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 **/
3238static ssize_t
3239lpfc_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;
3263error_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 **/
3284static ssize_t
3285lpfc_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
2334static const struct file_operations lpfc_debugfs_op_disc_trc = { 3319static 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
3409static 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
2424static const struct file_operations lpfc_idiag_op_queInfo = { 3419static 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
2432static const struct file_operations lpfc_idiag_op_queAcc = { 3427static 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
2442static const struct file_operations lpfc_idiag_op_drbAcc = { 3437static 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
3447static 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
3457static 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
3467static 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 **/
3486void
3487lpfc_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 **/
3585void
3586lpfc_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
2752debug_failed: 4031debug_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
9159out_disable_intr: 9158out_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 **/
4720static int 4725int
4721lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, 4726lpfc_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 **/
5525int
5526lpfc_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,