diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 59 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.h | 130 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 931 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.h | 48 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 44 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 18 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 19 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 14 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 32 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_version.h | 2 |
13 files changed, 1017 insertions, 290 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 60e98a62f308..02d53d89534f 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -805,6 +805,8 @@ struct lpfc_hba { | |||
805 | struct dentry *idiag_root; | 805 | struct dentry *idiag_root; |
806 | struct dentry *idiag_pci_cfg; | 806 | struct dentry *idiag_pci_cfg; |
807 | struct dentry *idiag_que_info; | 807 | struct dentry *idiag_que_info; |
808 | struct dentry *idiag_que_acc; | ||
809 | struct dentry *idiag_drb_acc; | ||
808 | #endif | 810 | #endif |
809 | 811 | ||
810 | /* Used for deferred freeing of ELS data buffers */ | 812 | /* Used for deferred freeing of ELS data buffers */ |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 77b2871d96b7..37e2a1272f86 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -2426,6 +2426,7 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2426 | { | 2426 | { |
2427 | struct bsg_job_data *dd_data; | 2427 | struct bsg_job_data *dd_data; |
2428 | struct fc_bsg_job *job; | 2428 | struct fc_bsg_job *job; |
2429 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
2429 | uint32_t size; | 2430 | uint32_t size; |
2430 | unsigned long flags; | 2431 | unsigned long flags; |
2431 | uint8_t *to; | 2432 | uint8_t *to; |
@@ -2469,9 +2470,8 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2469 | memcpy(to, from, size); | 2470 | memcpy(to, from, size); |
2470 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && | 2471 | } else if ((phba->sli_rev == LPFC_SLI_REV4) && |
2471 | (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) { | 2472 | (pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) { |
2472 | struct lpfc_mbx_nembed_cmd *nembed_sge = | 2473 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) |
2473 | (struct lpfc_mbx_nembed_cmd *) | 2474 | &pmboxq->u.mb.un.varWords[0]; |
2474 | &pmboxq->u.mb.un.varWords[0]; | ||
2475 | 2475 | ||
2476 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. | 2476 | from = (uint8_t *)dd_data->context_un.mbox.dmp->dma. |
2477 | virt; | 2477 | virt; |
@@ -2496,16 +2496,18 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | |||
2496 | job->reply_payload.sg_cnt, | 2496 | job->reply_payload.sg_cnt, |
2497 | from, size); | 2497 | from, size); |
2498 | job->reply->result = 0; | 2498 | job->reply->result = 0; |
2499 | 2499 | /* need to hold the lock until we set job->dd_data to NULL | |
2500 | * to hold off the timeout handler returning to the mid-layer | ||
2501 | * while we are still processing the job. | ||
2502 | */ | ||
2500 | job->dd_data = NULL; | 2503 | job->dd_data = NULL; |
2504 | dd_data->context_un.mbox.set_job = NULL; | ||
2505 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
2501 | job->job_done(job); | 2506 | job->job_done(job); |
2507 | } else { | ||
2508 | dd_data->context_un.mbox.set_job = NULL; | ||
2509 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
2502 | } | 2510 | } |
2503 | dd_data->context_un.mbox.set_job = NULL; | ||
2504 | /* need to hold the lock until we call job done to hold off | ||
2505 | * the timeout handler returning to the midlayer while | ||
2506 | * we are stillprocessing the job | ||
2507 | */ | ||
2508 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
2509 | 2511 | ||
2510 | kfree(dd_data->context_un.mbox.mb); | 2512 | kfree(dd_data->context_un.mbox.mb); |
2511 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); | 2513 | mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool); |
@@ -2644,6 +2646,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2644 | struct ulp_bde64 *rxbpl = NULL; | 2646 | struct ulp_bde64 *rxbpl = NULL; |
2645 | struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *) | 2647 | struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *) |
2646 | job->request->rqst_data.h_vendor.vendor_cmd; | 2648 | job->request->rqst_data.h_vendor.vendor_cmd; |
2649 | struct READ_EVENT_LOG_VAR *rdEventLog; | ||
2650 | uint32_t transmit_length, receive_length, mode; | ||
2651 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
2652 | struct mbox_header *header; | ||
2653 | struct ulp_bde64 *bde; | ||
2647 | uint8_t *ext = NULL; | 2654 | uint8_t *ext = NULL; |
2648 | int rc = 0; | 2655 | int rc = 0; |
2649 | uint8_t *from; | 2656 | uint8_t *from; |
@@ -2651,9 +2658,16 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2651 | /* in case no data is transferred */ | 2658 | /* in case no data is transferred */ |
2652 | job->reply->reply_payload_rcv_len = 0; | 2659 | job->reply->reply_payload_rcv_len = 0; |
2653 | 2660 | ||
2661 | /* sanity check to protect driver */ | ||
2662 | if (job->reply_payload.payload_len > BSG_MBOX_SIZE || | ||
2663 | job->request_payload.payload_len > BSG_MBOX_SIZE) { | ||
2664 | rc = -ERANGE; | ||
2665 | goto job_done; | ||
2666 | } | ||
2667 | |||
2654 | /* check if requested extended data lengths are valid */ | 2668 | /* check if requested extended data lengths are valid */ |
2655 | if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) || | 2669 | if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) || |
2656 | (mbox_req->outExtWLen > MAILBOX_EXT_SIZE)) { | 2670 | (mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) { |
2657 | rc = -ERANGE; | 2671 | rc = -ERANGE; |
2658 | goto job_done; | 2672 | goto job_done; |
2659 | } | 2673 | } |
@@ -2744,8 +2758,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2744 | * use ours | 2758 | * use ours |
2745 | */ | 2759 | */ |
2746 | if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) { | 2760 | if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) { |
2747 | uint32_t transmit_length = pmb->un.varWords[1]; | 2761 | transmit_length = pmb->un.varWords[1]; |
2748 | uint32_t receive_length = pmb->un.varWords[4]; | 2762 | receive_length = pmb->un.varWords[4]; |
2749 | /* transmit length cannot be greater than receive length or | 2763 | /* transmit length cannot be greater than receive length or |
2750 | * mailbox extension size | 2764 | * mailbox extension size |
2751 | */ | 2765 | */ |
@@ -2795,10 +2809,9 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2795 | from += sizeof(MAILBOX_t); | 2809 | from += sizeof(MAILBOX_t); |
2796 | memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); | 2810 | memcpy((uint8_t *)dmp->dma.virt, from, transmit_length); |
2797 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { | 2811 | } else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) { |
2798 | struct READ_EVENT_LOG_VAR *rdEventLog = | 2812 | rdEventLog = &pmb->un.varRdEventLog; |
2799 | &pmb->un.varRdEventLog ; | 2813 | receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; |
2800 | uint32_t receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize; | 2814 | mode = bf_get(lpfc_event_log, rdEventLog); |
2801 | uint32_t mode = bf_get(lpfc_event_log, rdEventLog); | ||
2802 | 2815 | ||
2803 | /* receive length cannot be greater than mailbox | 2816 | /* receive length cannot be greater than mailbox |
2804 | * extension size | 2817 | * extension size |
@@ -2843,7 +2856,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2843 | /* rebuild the command for sli4 using our own buffers | 2856 | /* rebuild the command for sli4 using our own buffers |
2844 | * like we do for biu diags | 2857 | * like we do for biu diags |
2845 | */ | 2858 | */ |
2846 | uint32_t receive_length = pmb->un.varWords[2]; | 2859 | receive_length = pmb->un.varWords[2]; |
2847 | /* receive length cannot be greater than mailbox | 2860 | /* receive length cannot be greater than mailbox |
2848 | * extension size | 2861 | * extension size |
2849 | */ | 2862 | */ |
@@ -2879,8 +2892,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2879 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); | 2892 | pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys); |
2880 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && | 2893 | } else if ((pmb->mbxCommand == MBX_UPDATE_CFG) && |
2881 | pmb->un.varUpdateCfg.co) { | 2894 | pmb->un.varUpdateCfg.co) { |
2882 | struct ulp_bde64 *bde = | 2895 | bde = (struct ulp_bde64 *)&pmb->un.varWords[4]; |
2883 | (struct ulp_bde64 *)&pmb->un.varWords[4]; | ||
2884 | 2896 | ||
2885 | /* bde size cannot be greater than mailbox ext size */ | 2897 | /* bde size cannot be greater than mailbox ext size */ |
2886 | if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) { | 2898 | if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) { |
@@ -2921,10 +2933,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
2921 | memcpy((uint8_t *)dmp->dma.virt, from, | 2933 | memcpy((uint8_t *)dmp->dma.virt, from, |
2922 | bde->tus.f.bdeSize); | 2934 | bde->tus.f.bdeSize); |
2923 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { | 2935 | } else if (pmb->mbxCommand == MBX_SLI4_CONFIG) { |
2924 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
2925 | struct mbox_header *header; | ||
2926 | uint32_t receive_length; | ||
2927 | |||
2928 | /* rebuild the command for sli4 using our own buffers | 2936 | /* rebuild the command for sli4 using our own buffers |
2929 | * like we do for biu diags | 2937 | * like we do for biu diags |
2930 | */ | 2938 | */ |
@@ -3386,6 +3394,7 @@ no_dd_data: | |||
3386 | job->dd_data = NULL; | 3394 | job->dd_data = NULL; |
3387 | return rc; | 3395 | return rc; |
3388 | } | 3396 | } |
3397 | |||
3389 | /** | 3398 | /** |
3390 | * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job | 3399 | * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job |
3391 | * @job: fc_bsg_job to handle | 3400 | * @job: fc_bsg_job to handle |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index a2c33e7c9152..b542aca6f5ae 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h | |||
@@ -109,3 +109,133 @@ struct menlo_response { | |||
109 | uint32_t xri; /* return the xri of the iocb exchange */ | 109 | uint32_t xri; /* return the xri of the iocb exchange */ |
110 | }; | 110 | }; |
111 | 111 | ||
112 | /* | ||
113 | * macros and data structures for handling sli-config mailbox command | ||
114 | * pass-through support, this header file is shared between user and | ||
115 | * kernel spaces, note the set of macros are duplicates from lpfc_hw4.h, | ||
116 | * with macro names prefixed with bsg_, as the macros defined in | ||
117 | * lpfc_hw4.h are not accessible from user space. | ||
118 | */ | ||
119 | |||
120 | /* Macros to deal with bit fields. Each bit field must have 3 #defines | ||
121 | * associated with it (_SHIFT, _MASK, and _WORD). | ||
122 | * EG. For a bit field that is in the 7th bit of the "field4" field of a | ||
123 | * structure and is 2 bits in size the following #defines must exist: | ||
124 | * struct temp { | ||
125 | * uint32_t field1; | ||
126 | * uint32_t field2; | ||
127 | * uint32_t field3; | ||
128 | * uint32_t field4; | ||
129 | * #define example_bit_field_SHIFT 7 | ||
130 | * #define example_bit_field_MASK 0x03 | ||
131 | * #define example_bit_field_WORD field4 | ||
132 | * uint32_t field5; | ||
133 | * }; | ||
134 | * Then the macros below may be used to get or set the value of that field. | ||
135 | * EG. To get the value of the bit field from the above example: | ||
136 | * struct temp t1; | ||
137 | * value = bsg_bf_get(example_bit_field, &t1); | ||
138 | * And then to set that bit field: | ||
139 | * bsg_bf_set(example_bit_field, &t1, 2); | ||
140 | * Or clear that bit field: | ||
141 | * bsg_bf_set(example_bit_field, &t1, 0); | ||
142 | */ | ||
143 | #define bsg_bf_get_le32(name, ptr) \ | ||
144 | ((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK) | ||
145 | #define bsg_bf_get(name, ptr) \ | ||
146 | (((ptr)->name##_WORD >> name##_SHIFT) & name##_MASK) | ||
147 | #define bsg_bf_set_le32(name, ptr, value) \ | ||
148 | ((ptr)->name##_WORD = cpu_to_le32(((((value) & \ | ||
149 | name##_MASK) << name##_SHIFT) | (le32_to_cpu((ptr)->name##_WORD) & \ | ||
150 | ~(name##_MASK << name##_SHIFT))))) | ||
151 | #define bsg_bf_set(name, ptr, value) \ | ||
152 | ((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \ | ||
153 | ((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT)))) | ||
154 | |||
155 | /* | ||
156 | * The sli_config structure specified here is based on the following | ||
157 | * restriction: | ||
158 | * | ||
159 | * -- SLI_CONFIG EMB=0, carrying MSEs, will carry subcommands without | ||
160 | * carrying HBD. | ||
161 | * -- SLI_CONFIG EMB=1, not carrying MSE, will carry subcommands with or | ||
162 | * without carrying HBDs. | ||
163 | */ | ||
164 | |||
165 | struct lpfc_sli_config_mse { | ||
166 | uint32_t pa_lo; | ||
167 | uint32_t pa_hi; | ||
168 | uint32_t buf_len; | ||
169 | #define lpfc_mbox_sli_config_mse_len_SHIFT 0 | ||
170 | #define lpfc_mbox_sli_config_mse_len_MASK 0xffffff | ||
171 | #define lpfc_mbox_sli_config_mse_len_WORD buf_len | ||
172 | }; | ||
173 | |||
174 | struct lpfc_sli_config_subcmd_hbd { | ||
175 | uint32_t buf_len; | ||
176 | #define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0 | ||
177 | #define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff | ||
178 | #define lpfc_mbox_sli_config_ecmn_hbd_len_WORD buf_len | ||
179 | uint32_t pa_lo; | ||
180 | uint32_t pa_hi; | ||
181 | }; | ||
182 | |||
183 | struct lpfc_sli_config_hdr { | ||
184 | uint32_t word1; | ||
185 | #define lpfc_mbox_hdr_emb_SHIFT 0 | ||
186 | #define lpfc_mbox_hdr_emb_MASK 0x00000001 | ||
187 | #define lpfc_mbox_hdr_emb_WORD word1 | ||
188 | #define lpfc_mbox_hdr_mse_cnt_SHIFT 3 | ||
189 | #define lpfc_mbox_hdr_mse_cnt_MASK 0x0000001f | ||
190 | #define lpfc_mbox_hdr_mse_cnt_WORD word1 | ||
191 | uint32_t payload_length; | ||
192 | uint32_t tag_lo; | ||
193 | uint32_t tag_hi; | ||
194 | uint32_t reserved5; | ||
195 | }; | ||
196 | |||
197 | struct lpfc_sli_config_generic { | ||
198 | struct lpfc_sli_config_hdr sli_config_hdr; | ||
199 | #define LPFC_MBX_SLI_CONFIG_MAX_MSE 19 | ||
200 | struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE]; | ||
201 | }; | ||
202 | |||
203 | struct lpfc_sli_config_subcmnd { | ||
204 | struct lpfc_sli_config_hdr sli_config_hdr; | ||
205 | uint32_t word6; | ||
206 | #define lpfc_subcmnd_opcode_SHIFT 0 | ||
207 | #define lpfc_subcmnd_opcode_MASK 0xff | ||
208 | #define lpfc_subcmnd_opcode_WORD word6 | ||
209 | #define lpfc_subcmnd_subsys_SHIFT 8 | ||
210 | #define lpfc_subcmnd_subsys_MASK 0xff | ||
211 | #define lpfc_subcmnd_subsys_WORD word6 | ||
212 | uint32_t timeout; | ||
213 | uint32_t request_length; | ||
214 | uint32_t word9; | ||
215 | #define lpfc_subcmnd_version_SHIFT 0 | ||
216 | #define lpfc_subcmnd_version_MASK 0xff | ||
217 | #define lpfc_subcmnd_version_WORD word9 | ||
218 | uint32_t word10; | ||
219 | #define lpfc_subcmnd_ask_rd_len_SHIFT 0 | ||
220 | #define lpfc_subcmnd_ask_rd_len_MASK 0xffffff | ||
221 | #define lpfc_subcmnd_ask_rd_len_WORD word10 | ||
222 | uint32_t rd_offset; | ||
223 | uint32_t obj_name[26]; | ||
224 | uint32_t hbd_count; | ||
225 | #define LPFC_MBX_SLI_CONFIG_MAX_HBD 10 | ||
226 | struct lpfc_sli_config_subcmd_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD]; | ||
227 | }; | ||
228 | |||
229 | struct lpfc_sli_config_mbox { | ||
230 | uint32_t word0; | ||
231 | #define lpfc_mqe_status_SHIFT 16 | ||
232 | #define lpfc_mqe_status_MASK 0x0000FFFF | ||
233 | #define lpfc_mqe_status_WORD word0 | ||
234 | #define lpfc_mqe_command_SHIFT 8 | ||
235 | #define lpfc_mqe_command_MASK 0x000000FF | ||
236 | #define lpfc_mqe_command_WORD word0 | ||
237 | union { | ||
238 | struct lpfc_sli_config_generic sli_config_generic; | ||
239 | struct lpfc_sli_config_subcmnd sli_config_subcmnd; | ||
240 | } un; | ||
241 | }; | ||
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 3d967741c708..c93fca058603 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1119,172 +1119,14 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) | |||
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | /* | 1121 | /* |
1122 | * --------------------------------- | ||
1122 | * iDiag debugfs file access methods | 1123 | * iDiag debugfs file access methods |
1123 | */ | 1124 | * --------------------------------- |
1124 | |||
1125 | /* | ||
1126 | * iDiag PCI config space register access methods: | ||
1127 | * | ||
1128 | * The PCI config space register accessees of read, write, read-modify-write | ||
1129 | * for set bits, and read-modify-write for clear bits to SLI4 PCI functions | ||
1130 | * are provided. In the proper SLI4 PCI function's debugfs iDiag directory, | ||
1131 | * | ||
1132 | * /sys/kernel/debug/lpfc/fn<#>/iDiag | ||
1133 | * | ||
1134 | * the access is through the debugfs entry pciCfg: | ||
1135 | * | ||
1136 | * 1. For PCI config space register read access, there are two read methods: | ||
1137 | * A) read a single PCI config space register in the size of a byte | ||
1138 | * (8 bits), a word (16 bits), or a dword (32 bits); or B) browse through | ||
1139 | * the 4K extended PCI config space. | ||
1140 | * | ||
1141 | * A) Read a single PCI config space register consists of two steps: | ||
1142 | * | ||
1143 | * Step-1: Set up PCI config space register read command, the command | ||
1144 | * syntax is, | ||
1145 | * | ||
1146 | * echo 1 <where> <count> > pciCfg | ||
1147 | * | ||
1148 | * where, 1 is the iDiag command for PCI config space read, <where> is the | ||
1149 | * offset from the beginning of the device's PCI config space to read from, | ||
1150 | * and <count> is the size of PCI config space register data to read back, | ||
1151 | * it will be 1 for reading a byte (8 bits), 2 for reading a word (16 bits | ||
1152 | * or 2 bytes), or 4 for reading a dword (32 bits or 4 bytes). | ||
1153 | * | ||
1154 | * Setp-2: Perform the debugfs read operation to execute the idiag command | ||
1155 | * set up in Step-1, | ||
1156 | * | ||
1157 | * cat pciCfg | ||
1158 | * | ||
1159 | * Examples: | ||
1160 | * To read PCI device's vendor-id and device-id from PCI config space, | ||
1161 | * | ||
1162 | * echo 1 0 4 > pciCfg | ||
1163 | * cat pciCfg | ||
1164 | * | ||
1165 | * To read PCI device's currnt command from config space, | ||
1166 | * | ||
1167 | * echo 1 4 2 > pciCfg | ||
1168 | * cat pciCfg | ||
1169 | * | ||
1170 | * B) Browse through the entire 4K extended PCI config space also consists | ||
1171 | * of two steps: | ||
1172 | * | ||
1173 | * Step-1: Set up PCI config space register browsing command, the command | ||
1174 | * syntax is, | ||
1175 | * | ||
1176 | * echo 1 0 4096 > pciCfg | ||
1177 | * | ||
1178 | * where, 1 is the iDiag command for PCI config space read, 0 must be used | ||
1179 | * as the offset for PCI config space register browse, and 4096 must be | ||
1180 | * used as the count for PCI config space register browse. | ||
1181 | * | ||
1182 | * Step-2: Repeately issue the debugfs read operation to browse through | ||
1183 | * the entire PCI config space registers: | ||
1184 | * | ||
1185 | * cat pciCfg | ||
1186 | * cat pciCfg | ||
1187 | * cat pciCfg | ||
1188 | * ... | ||
1189 | * | ||
1190 | * When browsing to the end of the 4K PCI config space, the browse method | ||
1191 | * shall wrap around to start reading from beginning again, and again... | ||
1192 | * | ||
1193 | * 2. For PCI config space register write access, it supports a single PCI | ||
1194 | * config space register write in the size of a byte (8 bits), a word | ||
1195 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1196 | * | ||
1197 | * echo 2 <where> <count> <value> > pciCfg | ||
1198 | * | ||
1199 | * where, 2 is the iDiag command for PCI config space write, <where> is | ||
1200 | * the offset from the beginning of the device's PCI config space to write | ||
1201 | * into, <count> is the size of data to write into the PCI config space, | ||
1202 | * it will be 1 for writing a byte (8 bits), 2 for writing a word (16 bits | ||
1203 | * or 2 bytes), or 4 for writing a dword (32 bits or 4 bytes), and <value> | ||
1204 | * is the data to be written into the PCI config space register at the | ||
1205 | * offset. | ||
1206 | * | ||
1207 | * Examples: | ||
1208 | * To disable PCI device's interrupt assertion, | ||
1209 | * | ||
1210 | * 1) Read in device's PCI config space register command field <cmd>: | ||
1211 | * | ||
1212 | * echo 1 4 2 > pciCfg | ||
1213 | * cat pciCfg | ||
1214 | * | ||
1215 | * 2) Set bit 10 (Interrupt Disable bit) in the <cmd>: | ||
1216 | * | ||
1217 | * <cmd> = <cmd> | (1 < 10) | ||
1218 | * | ||
1219 | * 3) Write the modified command back: | ||
1220 | * | ||
1221 | * echo 2 4 2 <cmd> > pciCfg | ||
1222 | * | ||
1223 | * 3. For PCI config space register set bits access, it supports a single PCI | ||
1224 | * config space register set bits in the size of a byte (8 bits), a word | ||
1225 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1226 | * | ||
1227 | * echo 3 <where> <count> <bitmask> > pciCfg | ||
1228 | * | ||
1229 | * where, 3 is the iDiag command for PCI config space set bits, <where> is | ||
1230 | * the offset from the beginning of the device's PCI config space to set | ||
1231 | * bits into, <count> is the size of the bitmask to set into the PCI config | ||
1232 | * space, it will be 1 for setting a byte (8 bits), 2 for setting a word | ||
1233 | * (16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 bytes), and | ||
1234 | * <bitmask> is the bitmask, indicating the bits to be set into the PCI | ||
1235 | * config space register at the offset. The logic performed to the content | ||
1236 | * of the PCI config space register, regval, is, | ||
1237 | * | ||
1238 | * regval |= <bitmask> | ||
1239 | * | ||
1240 | * 4. For PCI config space register clear bits access, it supports a single | ||
1241 | * PCI config space register clear bits in the size of a byte (8 bits), | ||
1242 | * a word (16 bits), or a dword (32 bits). The command syntax is, | ||
1243 | * | ||
1244 | * echo 4 <where> <count> <bitmask> > pciCfg | ||
1245 | * | ||
1246 | * where, 4 is the iDiag command for PCI config space clear bits, <where> | ||
1247 | * is the offset from the beginning of the device's PCI config space to | ||
1248 | * clear bits from, <count> is the size of the bitmask to set into the PCI | ||
1249 | * config space, it will be 1 for setting a byte (8 bits), 2 for setting | ||
1250 | * a word(16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 | ||
1251 | * bytes), and <bitmask> is the bitmask, indicating the bits to be cleared | ||
1252 | * from the PCI config space register at the offset. the logic performed | ||
1253 | * to the content of the PCI config space register, regval, is, | ||
1254 | * | ||
1255 | * regval &= ~<bitmask> | ||
1256 | * | ||
1257 | * Note, for all single register read, write, set bits, or clear bits access, | ||
1258 | * the offset (<where>) must be aligned with the size of the data: | ||
1259 | * | ||
1260 | * For data size of byte (8 bits), the offset must be aligned to the byte | ||
1261 | * boundary; for data size of word (16 bits), the offset must be aligned | ||
1262 | * to the word boundary; while for data size of dword (32 bits), the offset | ||
1263 | * must be aligned to the dword boundary. Otherwise, the interface will | ||
1264 | * return the error: | ||
1265 | * | 1125 | * |
1266 | * "-bash: echo: write error: Invalid argument". | 1126 | * All access methods are through the proper SLI4 PCI function's debugfs |
1127 | * iDiag directory: | ||
1267 | * | 1128 | * |
1268 | * For example: | 1129 | * /sys/kernel/debug/lpfc/fn<#>/iDiag |
1269 | * | ||
1270 | * echo 1 2 4 > pciCfg | ||
1271 | * -bash: echo: write error: Invalid argument | ||
1272 | * | ||
1273 | * Note also, all of the numbers in the command fields for all read, write, | ||
1274 | * set bits, and clear bits PCI config space register command fields can be | ||
1275 | * either decimal or hex. | ||
1276 | * | ||
1277 | * For example, | ||
1278 | * echo 1 0 4096 > pciCfg | ||
1279 | * | ||
1280 | * will be the same as | ||
1281 | * echo 1 0 0x1000 > pciCfg | ||
1282 | * | ||
1283 | * And, | ||
1284 | * echo 2 155 1 10 > pciCfg | ||
1285 | * | ||
1286 | * will be | ||
1287 | * echo 2 0x9b 1 0xa > pciCfg | ||
1288 | */ | 1130 | */ |
1289 | 1131 | ||
1290 | /** | 1132 | /** |
@@ -1331,10 +1173,10 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes, | |||
1331 | for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { | 1173 | for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { |
1332 | step_str = strsep(&pbuf, "\t "); | 1174 | step_str = strsep(&pbuf, "\t "); |
1333 | if (!step_str) | 1175 | if (!step_str) |
1334 | return 0; | 1176 | return i; |
1335 | idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); | 1177 | idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); |
1336 | } | 1178 | } |
1337 | return 0; | 1179 | return i; |
1338 | } | 1180 | } |
1339 | 1181 | ||
1340 | /** | 1182 | /** |
@@ -1403,7 +1245,7 @@ lpfc_idiag_release(struct inode *inode, struct file *file) | |||
1403 | * Description: | 1245 | * Description: |
1404 | * This routine frees the buffer that was allocated when the debugfs file | 1246 | * This routine frees the buffer that was allocated when the debugfs file |
1405 | * was opened. It also reset the fields in the idiag command struct in the | 1247 | * was opened. It also reset the fields in the idiag command struct in the |
1406 | * case the command is not continuous browsing of the data structure. | 1248 | * case of command for write operation. |
1407 | * | 1249 | * |
1408 | * Returns: | 1250 | * Returns: |
1409 | * This function returns zero. | 1251 | * This function returns zero. |
@@ -1413,18 +1255,20 @@ lpfc_idiag_cmd_release(struct inode *inode, struct file *file) | |||
1413 | { | 1255 | { |
1414 | struct lpfc_debug *debug = file->private_data; | 1256 | struct lpfc_debug *debug = file->private_data; |
1415 | 1257 | ||
1416 | /* Read PCI config register, if not read all, clear command fields */ | 1258 | if (debug->op == LPFC_IDIAG_OP_WR) { |
1417 | if ((debug->op == LPFC_IDIAG_OP_RD) && | 1259 | switch (idiag.cmd.opcode) { |
1418 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD)) | 1260 | case LPFC_IDIAG_CMD_PCICFG_WR: |
1419 | if ((idiag.cmd.data[1] == sizeof(uint8_t)) || | 1261 | case LPFC_IDIAG_CMD_PCICFG_ST: |
1420 | (idiag.cmd.data[1] == sizeof(uint16_t)) || | 1262 | case LPFC_IDIAG_CMD_PCICFG_CL: |
1421 | (idiag.cmd.data[1] == sizeof(uint32_t))) | 1263 | case LPFC_IDIAG_CMD_QUEACC_WR: |
1264 | case LPFC_IDIAG_CMD_QUEACC_ST: | ||
1265 | case LPFC_IDIAG_CMD_QUEACC_CL: | ||
1422 | memset(&idiag, 0, sizeof(idiag)); | 1266 | memset(&idiag, 0, sizeof(idiag)); |
1423 | 1267 | break; | |
1424 | /* Write PCI config register, clear command fields */ | 1268 | default: |
1425 | if ((debug->op == LPFC_IDIAG_OP_WR) && | 1269 | break; |
1426 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)) | 1270 | } |
1427 | memset(&idiag, 0, sizeof(idiag)); | 1271 | } |
1428 | 1272 | ||
1429 | /* Free the buffers to the file operation */ | 1273 | /* Free the buffers to the file operation */ |
1430 | kfree(debug->buffer); | 1274 | kfree(debug->buffer); |
@@ -1504,7 +1348,7 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, | |||
1504 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | 1348 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, |
1505 | "%03x: %08x\n", where, u32val); | 1349 | "%03x: %08x\n", where, u32val); |
1506 | break; | 1350 | break; |
1507 | case LPFC_PCI_CFG_SIZE: /* browse all */ | 1351 | case LPFC_PCI_CFG_BROWSE: /* browse all */ |
1508 | goto pcicfg_browse; | 1352 | goto pcicfg_browse; |
1509 | break; | 1353 | break; |
1510 | default: | 1354 | default: |
@@ -1586,16 +1430,21 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | |||
1586 | debug->op = LPFC_IDIAG_OP_WR; | 1430 | debug->op = LPFC_IDIAG_OP_WR; |
1587 | 1431 | ||
1588 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | 1432 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); |
1589 | if (rc) | 1433 | if (rc < 0) |
1590 | return rc; | 1434 | return rc; |
1591 | 1435 | ||
1592 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | 1436 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { |
1437 | /* Sanity check on PCI config read command line arguments */ | ||
1438 | if (rc != LPFC_PCI_CFG_RD_CMD_ARG) | ||
1439 | goto error_out; | ||
1593 | /* Read command from PCI config space, set up command fields */ | 1440 | /* Read command from PCI config space, set up command fields */ |
1594 | where = idiag.cmd.data[0]; | 1441 | where = idiag.cmd.data[0]; |
1595 | count = idiag.cmd.data[1]; | 1442 | count = idiag.cmd.data[1]; |
1596 | if (count == LPFC_PCI_CFG_SIZE) { | 1443 | if (count == LPFC_PCI_CFG_BROWSE) { |
1597 | if (where != 0) | 1444 | if (where % sizeof(uint32_t)) |
1598 | goto error_out; | 1445 | goto error_out; |
1446 | /* Starting offset to browse */ | ||
1447 | idiag.offset.last_rd = where; | ||
1599 | } else if ((count != sizeof(uint8_t)) && | 1448 | } else if ((count != sizeof(uint8_t)) && |
1600 | (count != sizeof(uint16_t)) && | 1449 | (count != sizeof(uint16_t)) && |
1601 | (count != sizeof(uint32_t))) | 1450 | (count != sizeof(uint32_t))) |
@@ -1621,6 +1470,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | |||
1621 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || | 1470 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || |
1622 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || | 1471 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || |
1623 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | 1472 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { |
1473 | /* Sanity check on PCI config write command line arguments */ | ||
1474 | if (rc != LPFC_PCI_CFG_WR_CMD_ARG) | ||
1475 | goto error_out; | ||
1624 | /* Write command to PCI config space, read-modify-write */ | 1476 | /* Write command to PCI config space, read-modify-write */ |
1625 | where = idiag.cmd.data[0]; | 1477 | where = idiag.cmd.data[0]; |
1626 | count = idiag.cmd.data[1]; | 1478 | count = idiag.cmd.data[1]; |
@@ -1753,10 +1605,12 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1753 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1605 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1754 | "Slow-path EQ information:\n"); | 1606 | "Slow-path EQ information:\n"); |
1755 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1607 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1756 | "\tID [%02d], EQE-COUNT [%04d], " | 1608 | "\tEQID[%02d], " |
1757 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | 1609 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1610 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", | ||
1758 | phba->sli4_hba.sp_eq->queue_id, | 1611 | phba->sli4_hba.sp_eq->queue_id, |
1759 | phba->sli4_hba.sp_eq->entry_count, | 1612 | phba->sli4_hba.sp_eq->entry_count, |
1613 | phba->sli4_hba.sp_eq->entry_size, | ||
1760 | phba->sli4_hba.sp_eq->host_index, | 1614 | phba->sli4_hba.sp_eq->host_index, |
1761 | phba->sli4_hba.sp_eq->hba_index); | 1615 | phba->sli4_hba.sp_eq->hba_index); |
1762 | 1616 | ||
@@ -1765,10 +1619,12 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1765 | "Fast-path EQ information:\n"); | 1619 | "Fast-path EQ information:\n"); |
1766 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | 1620 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { |
1767 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1621 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1768 | "\tID [%02d], EQE-COUNT [%04d], " | 1622 | "\tEQID[%02d], " |
1769 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | 1623 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1624 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", | ||
1770 | phba->sli4_hba.fp_eq[fcp_qidx]->queue_id, | 1625 | phba->sli4_hba.fp_eq[fcp_qidx]->queue_id, |
1771 | phba->sli4_hba.fp_eq[fcp_qidx]->entry_count, | 1626 | phba->sli4_hba.fp_eq[fcp_qidx]->entry_count, |
1627 | phba->sli4_hba.fp_eq[fcp_qidx]->entry_size, | ||
1772 | phba->sli4_hba.fp_eq[fcp_qidx]->host_index, | 1628 | phba->sli4_hba.fp_eq[fcp_qidx]->host_index, |
1773 | phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); | 1629 | phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); |
1774 | } | 1630 | } |
@@ -1776,89 +1632,101 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1776 | 1632 | ||
1777 | /* Get mailbox complete queue information */ | 1633 | /* Get mailbox complete queue information */ |
1778 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1634 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1779 | "Mailbox CQ information:\n"); | 1635 | "Slow-path MBX CQ information:\n"); |
1780 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1636 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1781 | "\t\tAssociated EQ-ID [%02d]:\n", | 1637 | "Associated EQID[%02d]:\n", |
1782 | phba->sli4_hba.mbx_cq->assoc_qid); | 1638 | phba->sli4_hba.mbx_cq->assoc_qid); |
1783 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1639 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1784 | "\tID [%02d], CQE-COUNT [%04d], " | 1640 | "\tCQID[%02d], " |
1785 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | 1641 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1642 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", | ||
1786 | phba->sli4_hba.mbx_cq->queue_id, | 1643 | phba->sli4_hba.mbx_cq->queue_id, |
1787 | phba->sli4_hba.mbx_cq->entry_count, | 1644 | phba->sli4_hba.mbx_cq->entry_count, |
1645 | phba->sli4_hba.mbx_cq->entry_size, | ||
1788 | phba->sli4_hba.mbx_cq->host_index, | 1646 | phba->sli4_hba.mbx_cq->host_index, |
1789 | phba->sli4_hba.mbx_cq->hba_index); | 1647 | phba->sli4_hba.mbx_cq->hba_index); |
1790 | 1648 | ||
1791 | /* Get slow-path complete queue information */ | 1649 | /* Get slow-path complete queue information */ |
1792 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1650 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1793 | "Slow-path CQ information:\n"); | 1651 | "Slow-path ELS CQ information:\n"); |
1794 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1652 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1795 | "\t\tAssociated EQ-ID [%02d]:\n", | 1653 | "Associated EQID[%02d]:\n", |
1796 | phba->sli4_hba.els_cq->assoc_qid); | 1654 | phba->sli4_hba.els_cq->assoc_qid); |
1797 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1655 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1798 | "\tID [%02d], CQE-COUNT [%04d], " | 1656 | "\tCQID [%02d], " |
1799 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | 1657 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1658 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", | ||
1800 | phba->sli4_hba.els_cq->queue_id, | 1659 | phba->sli4_hba.els_cq->queue_id, |
1801 | phba->sli4_hba.els_cq->entry_count, | 1660 | phba->sli4_hba.els_cq->entry_count, |
1661 | phba->sli4_hba.els_cq->entry_size, | ||
1802 | phba->sli4_hba.els_cq->host_index, | 1662 | phba->sli4_hba.els_cq->host_index, |
1803 | phba->sli4_hba.els_cq->hba_index); | 1663 | phba->sli4_hba.els_cq->hba_index); |
1804 | 1664 | ||
1805 | /* Get fast-path complete queue information */ | 1665 | /* Get fast-path complete queue information */ |
1806 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1666 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1807 | "Fast-path CQ information:\n"); | 1667 | "Fast-path FCP CQ information:\n"); |
1808 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | 1668 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { |
1809 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1669 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1810 | "\t\tAssociated EQ-ID [%02d]:\n", | 1670 | "Associated EQID[%02d]:\n", |
1811 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); | 1671 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); |
1812 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1672 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1813 | "\tID [%02d], EQE-COUNT [%04d], " | 1673 | "\tCQID[%02d], " |
1814 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | 1674 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1815 | phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id, | 1675 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", |
1816 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count, | 1676 | phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id, |
1817 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | 1677 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count, |
1818 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | 1678 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, |
1679 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | ||
1680 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | ||
1819 | } | 1681 | } |
1820 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | 1682 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); |
1821 | 1683 | ||
1822 | /* Get mailbox queue information */ | 1684 | /* Get mailbox queue information */ |
1823 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1685 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1824 | "Mailbox MQ information:\n"); | 1686 | "Slow-path MBX MQ information:\n"); |
1825 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1687 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1826 | "\t\tAssociated CQ-ID [%02d]:\n", | 1688 | "Associated CQID[%02d]:\n", |
1827 | phba->sli4_hba.mbx_wq->assoc_qid); | 1689 | phba->sli4_hba.mbx_wq->assoc_qid); |
1828 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1690 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1829 | "\tID [%02d], MQE-COUNT [%04d], " | 1691 | "\tWQID[%02d], " |
1830 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | 1692 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1693 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", | ||
1831 | phba->sli4_hba.mbx_wq->queue_id, | 1694 | phba->sli4_hba.mbx_wq->queue_id, |
1832 | phba->sli4_hba.mbx_wq->entry_count, | 1695 | phba->sli4_hba.mbx_wq->entry_count, |
1696 | phba->sli4_hba.mbx_wq->entry_size, | ||
1833 | phba->sli4_hba.mbx_wq->host_index, | 1697 | phba->sli4_hba.mbx_wq->host_index, |
1834 | phba->sli4_hba.mbx_wq->hba_index); | 1698 | phba->sli4_hba.mbx_wq->hba_index); |
1835 | 1699 | ||
1836 | /* Get slow-path work queue information */ | 1700 | /* Get slow-path work queue information */ |
1837 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1701 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1838 | "Slow-path WQ information:\n"); | 1702 | "Slow-path ELS WQ information:\n"); |
1839 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1703 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1840 | "\t\tAssociated CQ-ID [%02d]:\n", | 1704 | "Associated CQID[%02d]:\n", |
1841 | phba->sli4_hba.els_wq->assoc_qid); | 1705 | phba->sli4_hba.els_wq->assoc_qid); |
1842 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1706 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1843 | "\tID [%02d], WQE-COUNT [%04d], " | 1707 | "\tWQID[%02d], " |
1844 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | 1708 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1709 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", | ||
1845 | phba->sli4_hba.els_wq->queue_id, | 1710 | phba->sli4_hba.els_wq->queue_id, |
1846 | phba->sli4_hba.els_wq->entry_count, | 1711 | phba->sli4_hba.els_wq->entry_count, |
1712 | phba->sli4_hba.els_wq->entry_size, | ||
1847 | phba->sli4_hba.els_wq->host_index, | 1713 | phba->sli4_hba.els_wq->host_index, |
1848 | phba->sli4_hba.els_wq->hba_index); | 1714 | phba->sli4_hba.els_wq->hba_index); |
1849 | 1715 | ||
1850 | /* Get fast-path work queue information */ | 1716 | /* Get fast-path work queue information */ |
1851 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1717 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1852 | "Fast-path WQ information:\n"); | 1718 | "Fast-path FCP WQ information:\n"); |
1853 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { | 1719 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { |
1854 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1720 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1855 | "\t\tAssociated CQ-ID [%02d]:\n", | 1721 | "Associated CQID[%02d]:\n", |
1856 | phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); | 1722 | phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); |
1857 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1723 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1858 | "\tID [%02d], WQE-COUNT [%04d], " | 1724 | "\tWQID[%02d], " |
1859 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | 1725 | "QE-COUNT[%04d], WQE-SIZE[%04d], " |
1726 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", | ||
1860 | phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id, | 1727 | phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id, |
1861 | phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count, | 1728 | phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count, |
1729 | phba->sli4_hba.fcp_wq[fcp_qidx]->entry_size, | ||
1862 | phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, | 1730 | phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, |
1863 | phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); | 1731 | phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); |
1864 | } | 1732 | } |
@@ -1868,26 +1736,597 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | |||
1868 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1736 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1869 | "Slow-path RQ information:\n"); | 1737 | "Slow-path RQ information:\n"); |
1870 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1738 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1871 | "\t\tAssociated CQ-ID [%02d]:\n", | 1739 | "Associated CQID[%02d]:\n", |
1872 | phba->sli4_hba.hdr_rq->assoc_qid); | 1740 | phba->sli4_hba.hdr_rq->assoc_qid); |
1873 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1741 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1874 | "\tID [%02d], RHQE-COUNT [%04d], " | 1742 | "\tHQID[%02d], " |
1875 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | 1743 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1744 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", | ||
1876 | phba->sli4_hba.hdr_rq->queue_id, | 1745 | phba->sli4_hba.hdr_rq->queue_id, |
1877 | phba->sli4_hba.hdr_rq->entry_count, | 1746 | phba->sli4_hba.hdr_rq->entry_count, |
1747 | phba->sli4_hba.hdr_rq->entry_size, | ||
1878 | phba->sli4_hba.hdr_rq->host_index, | 1748 | phba->sli4_hba.hdr_rq->host_index, |
1879 | phba->sli4_hba.hdr_rq->hba_index); | 1749 | phba->sli4_hba.hdr_rq->hba_index); |
1880 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | 1750 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, |
1881 | "\tID [%02d], RDQE-COUNT [%04d], " | 1751 | "\tDQID[%02d], " |
1882 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | 1752 | "QE-COUNT[%04d], QE-SIZE[%04d], " |
1753 | "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", | ||
1883 | phba->sli4_hba.dat_rq->queue_id, | 1754 | phba->sli4_hba.dat_rq->queue_id, |
1884 | phba->sli4_hba.dat_rq->entry_count, | 1755 | phba->sli4_hba.dat_rq->entry_count, |
1756 | phba->sli4_hba.dat_rq->entry_size, | ||
1885 | phba->sli4_hba.dat_rq->host_index, | 1757 | phba->sli4_hba.dat_rq->host_index, |
1886 | phba->sli4_hba.dat_rq->hba_index); | 1758 | phba->sli4_hba.dat_rq->hba_index); |
1887 | 1759 | ||
1888 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | 1760 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); |
1889 | } | 1761 | } |
1890 | 1762 | ||
1763 | /** | ||
1764 | * lpfc_idiag_que_param_check - queue access command parameter sanity check | ||
1765 | * @q: The pointer to queue structure. | ||
1766 | * @index: The index into a queue entry. | ||
1767 | * @count: The number of queue entries to access. | ||
1768 | * | ||
1769 | * Description: | ||
1770 | * The routine performs sanity check on device queue access method commands. | ||
1771 | * | ||
1772 | * Returns: | ||
1773 | * This function returns -EINVAL when fails the sanity check, otherwise, it | ||
1774 | * returns 0. | ||
1775 | **/ | ||
1776 | static int | ||
1777 | lpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count) | ||
1778 | { | ||
1779 | /* Only support single entry read or browsing */ | ||
1780 | if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE)) | ||
1781 | return -EINVAL; | ||
1782 | if (index > q->entry_count - 1) | ||
1783 | return -EINVAL; | ||
1784 | return 0; | ||
1785 | } | ||
1786 | |||
1787 | /** | ||
1788 | * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index | ||
1789 | * @pbuffer: The pointer to buffer to copy the read data into. | ||
1790 | * @pque: The pointer to the queue to be read. | ||
1791 | * @index: The index into the queue entry. | ||
1792 | * | ||
1793 | * Description: | ||
1794 | * This routine reads out a single entry from the given queue's index location | ||
1795 | * and copies it into the buffer provided. | ||
1796 | * | ||
1797 | * Returns: | ||
1798 | * This function returns 0 when it fails, otherwise, it returns the length of | ||
1799 | * the data read into the buffer provided. | ||
1800 | **/ | ||
1801 | static int | ||
1802 | lpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque, | ||
1803 | uint32_t index) | ||
1804 | { | ||
1805 | int offset, esize; | ||
1806 | uint32_t *pentry; | ||
1807 | |||
1808 | if (!pbuffer || !pque) | ||
1809 | return 0; | ||
1810 | |||
1811 | esize = pque->entry_size; | ||
1812 | len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, | ||
1813 | "QE-INDEX[%04d]:\n", index); | ||
1814 | |||
1815 | offset = 0; | ||
1816 | pentry = pque->qe[index].address; | ||
1817 | while (esize > 0) { | ||
1818 | len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, | ||
1819 | "%08x ", *pentry); | ||
1820 | pentry++; | ||
1821 | offset += sizeof(uint32_t); | ||
1822 | esize -= sizeof(uint32_t); | ||
1823 | if (esize > 0 && !(offset % (4 * sizeof(uint32_t)))) | ||
1824 | len += snprintf(pbuffer+len, | ||
1825 | LPFC_QUE_ACC_BUF_SIZE-len, "\n"); | ||
1826 | } | ||
1827 | len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n"); | ||
1828 | |||
1829 | return len; | ||
1830 | } | ||
1831 | |||
1832 | /** | ||
1833 | * lpfc_idiag_queacc_read - idiag debugfs read port queue | ||
1834 | * @file: The file pointer to read from. | ||
1835 | * @buf: The buffer to copy the data to. | ||
1836 | * @nbytes: The number of bytes to read. | ||
1837 | * @ppos: The position in the file to start reading from. | ||
1838 | * | ||
1839 | * Description: | ||
1840 | * This routine reads data from the @phba device queue memory according to the | ||
1841 | * idiag command, and copies to user @buf. Depending on the queue dump read | ||
1842 | * command setup, it does either a single queue entry read or browing through | ||
1843 | * all entries of the queue. | ||
1844 | * | ||
1845 | * Returns: | ||
1846 | * This function returns the amount of data that was read (this could be less | ||
1847 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1848 | **/ | ||
1849 | static ssize_t | ||
1850 | lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes, | ||
1851 | loff_t *ppos) | ||
1852 | { | ||
1853 | struct lpfc_debug *debug = file->private_data; | ||
1854 | uint32_t last_index, index, count; | ||
1855 | struct lpfc_queue *pque = NULL; | ||
1856 | char *pbuffer; | ||
1857 | int len = 0; | ||
1858 | |||
1859 | /* This is a user read operation */ | ||
1860 | debug->op = LPFC_IDIAG_OP_RD; | ||
1861 | |||
1862 | if (!debug->buffer) | ||
1863 | debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL); | ||
1864 | if (!debug->buffer) | ||
1865 | return 0; | ||
1866 | pbuffer = debug->buffer; | ||
1867 | |||
1868 | if (*ppos) | ||
1869 | return 0; | ||
1870 | |||
1871 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { | ||
1872 | index = idiag.cmd.data[2]; | ||
1873 | count = idiag.cmd.data[3]; | ||
1874 | pque = (struct lpfc_queue *)idiag.ptr_private; | ||
1875 | } else | ||
1876 | return 0; | ||
1877 | |||
1878 | /* Browse the queue starting from index */ | ||
1879 | if (count == LPFC_QUE_ACC_BROWSE) | ||
1880 | goto que_browse; | ||
1881 | |||
1882 | /* Read a single entry from the queue */ | ||
1883 | len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index); | ||
1884 | |||
1885 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1886 | |||
1887 | que_browse: | ||
1888 | |||
1889 | /* Browse all entries from the queue */ | ||
1890 | last_index = idiag.offset.last_rd; | ||
1891 | index = last_index; | ||
1892 | |||
1893 | while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) { | ||
1894 | len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index); | ||
1895 | index++; | ||
1896 | if (index > pque->entry_count - 1) | ||
1897 | break; | ||
1898 | } | ||
1899 | |||
1900 | /* Set up the offset for next portion of pci cfg read */ | ||
1901 | if (index > pque->entry_count - 1) | ||
1902 | index = 0; | ||
1903 | idiag.offset.last_rd = index; | ||
1904 | |||
1905 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1906 | } | ||
1907 | |||
1908 | /** | ||
1909 | * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands | ||
1910 | * @file: The file pointer to read from. | ||
1911 | * @buf: The buffer to copy the user data from. | ||
1912 | * @nbytes: The number of bytes to get. | ||
1913 | * @ppos: The position in the file to start reading from. | ||
1914 | * | ||
1915 | * This routine get the debugfs idiag command struct from user space and then | ||
1916 | * perform the syntax check for port queue read (dump) or write (set) command | ||
1917 | * accordingly. In the case of port queue read command, it sets up the command | ||
1918 | * in the idiag command struct for the following debugfs read operation. In | ||
1919 | * the case of port queue write operation, it executes the write operation | ||
1920 | * into the port queue entry accordingly. | ||
1921 | * | ||
1922 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
1923 | * In case of error conditions, it returns proper error code back to the user | ||
1924 | * space. | ||
1925 | **/ | ||
1926 | static ssize_t | ||
1927 | lpfc_idiag_queacc_write(struct file *file, const char __user *buf, | ||
1928 | size_t nbytes, loff_t *ppos) | ||
1929 | { | ||
1930 | struct lpfc_debug *debug = file->private_data; | ||
1931 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1932 | uint32_t qidx, quetp, queid, index, count, offset, value; | ||
1933 | uint32_t *pentry; | ||
1934 | struct lpfc_queue *pque; | ||
1935 | int rc; | ||
1936 | |||
1937 | /* This is a user write operation */ | ||
1938 | debug->op = LPFC_IDIAG_OP_WR; | ||
1939 | |||
1940 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
1941 | if (rc < 0) | ||
1942 | return rc; | ||
1943 | |||
1944 | /* Get and sanity check on command feilds */ | ||
1945 | quetp = idiag.cmd.data[0]; | ||
1946 | queid = idiag.cmd.data[1]; | ||
1947 | index = idiag.cmd.data[2]; | ||
1948 | count = idiag.cmd.data[3]; | ||
1949 | offset = idiag.cmd.data[4]; | ||
1950 | value = idiag.cmd.data[5]; | ||
1951 | |||
1952 | /* Sanity check on command line arguments */ | ||
1953 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || | ||
1954 | idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST || | ||
1955 | idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) { | ||
1956 | if (rc != LPFC_QUE_ACC_WR_CMD_ARG) | ||
1957 | goto error_out; | ||
1958 | if (count != 1) | ||
1959 | goto error_out; | ||
1960 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { | ||
1961 | if (rc != LPFC_QUE_ACC_RD_CMD_ARG) | ||
1962 | goto error_out; | ||
1963 | } else | ||
1964 | goto error_out; | ||
1965 | |||
1966 | switch (quetp) { | ||
1967 | case LPFC_IDIAG_EQ: | ||
1968 | /* Slow-path event queue */ | ||
1969 | if (phba->sli4_hba.sp_eq->queue_id == queid) { | ||
1970 | /* Sanity check */ | ||
1971 | rc = lpfc_idiag_que_param_check( | ||
1972 | phba->sli4_hba.sp_eq, index, count); | ||
1973 | if (rc) | ||
1974 | goto error_out; | ||
1975 | idiag.ptr_private = phba->sli4_hba.sp_eq; | ||
1976 | goto pass_check; | ||
1977 | } | ||
1978 | /* Fast-path event queue */ | ||
1979 | for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { | ||
1980 | if (phba->sli4_hba.fp_eq[qidx]->queue_id == queid) { | ||
1981 | /* Sanity check */ | ||
1982 | rc = lpfc_idiag_que_param_check( | ||
1983 | phba->sli4_hba.fp_eq[qidx], | ||
1984 | index, count); | ||
1985 | if (rc) | ||
1986 | goto error_out; | ||
1987 | idiag.ptr_private = phba->sli4_hba.fp_eq[qidx]; | ||
1988 | goto pass_check; | ||
1989 | } | ||
1990 | } | ||
1991 | goto error_out; | ||
1992 | break; | ||
1993 | case LPFC_IDIAG_CQ: | ||
1994 | /* MBX complete queue */ | ||
1995 | if (phba->sli4_hba.mbx_cq->queue_id == queid) { | ||
1996 | /* Sanity check */ | ||
1997 | rc = lpfc_idiag_que_param_check( | ||
1998 | phba->sli4_hba.mbx_cq, index, count); | ||
1999 | if (rc) | ||
2000 | goto error_out; | ||
2001 | idiag.ptr_private = phba->sli4_hba.mbx_cq; | ||
2002 | goto pass_check; | ||
2003 | } | ||
2004 | /* ELS complete queue */ | ||
2005 | if (phba->sli4_hba.els_cq->queue_id == queid) { | ||
2006 | /* Sanity check */ | ||
2007 | rc = lpfc_idiag_que_param_check( | ||
2008 | phba->sli4_hba.els_cq, index, count); | ||
2009 | if (rc) | ||
2010 | goto error_out; | ||
2011 | idiag.ptr_private = phba->sli4_hba.els_cq; | ||
2012 | goto pass_check; | ||
2013 | } | ||
2014 | /* FCP complete queue */ | ||
2015 | for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { | ||
2016 | if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { | ||
2017 | /* Sanity check */ | ||
2018 | rc = lpfc_idiag_que_param_check( | ||
2019 | phba->sli4_hba.fcp_cq[qidx], | ||
2020 | index, count); | ||
2021 | if (rc) | ||
2022 | goto error_out; | ||
2023 | idiag.ptr_private = | ||
2024 | phba->sli4_hba.fcp_cq[qidx]; | ||
2025 | goto pass_check; | ||
2026 | } | ||
2027 | } | ||
2028 | goto error_out; | ||
2029 | break; | ||
2030 | case LPFC_IDIAG_MQ: | ||
2031 | /* MBX work queue */ | ||
2032 | if (phba->sli4_hba.mbx_wq->queue_id == queid) { | ||
2033 | /* Sanity check */ | ||
2034 | rc = lpfc_idiag_que_param_check( | ||
2035 | phba->sli4_hba.mbx_wq, index, count); | ||
2036 | if (rc) | ||
2037 | goto error_out; | ||
2038 | idiag.ptr_private = phba->sli4_hba.mbx_wq; | ||
2039 | goto pass_check; | ||
2040 | } | ||
2041 | break; | ||
2042 | case LPFC_IDIAG_WQ: | ||
2043 | /* ELS work queue */ | ||
2044 | if (phba->sli4_hba.els_wq->queue_id == queid) { | ||
2045 | /* Sanity check */ | ||
2046 | rc = lpfc_idiag_que_param_check( | ||
2047 | phba->sli4_hba.els_wq, index, count); | ||
2048 | if (rc) | ||
2049 | goto error_out; | ||
2050 | idiag.ptr_private = phba->sli4_hba.els_wq; | ||
2051 | goto pass_check; | ||
2052 | } | ||
2053 | /* FCP work queue */ | ||
2054 | for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) { | ||
2055 | if (phba->sli4_hba.fcp_wq[qidx]->queue_id == queid) { | ||
2056 | /* Sanity check */ | ||
2057 | rc = lpfc_idiag_que_param_check( | ||
2058 | phba->sli4_hba.fcp_wq[qidx], | ||
2059 | index, count); | ||
2060 | if (rc) | ||
2061 | goto error_out; | ||
2062 | idiag.ptr_private = | ||
2063 | phba->sli4_hba.fcp_wq[qidx]; | ||
2064 | goto pass_check; | ||
2065 | } | ||
2066 | } | ||
2067 | goto error_out; | ||
2068 | break; | ||
2069 | case LPFC_IDIAG_RQ: | ||
2070 | /* HDR queue */ | ||
2071 | if (phba->sli4_hba.hdr_rq->queue_id == queid) { | ||
2072 | /* Sanity check */ | ||
2073 | rc = lpfc_idiag_que_param_check( | ||
2074 | phba->sli4_hba.hdr_rq, index, count); | ||
2075 | if (rc) | ||
2076 | goto error_out; | ||
2077 | idiag.ptr_private = phba->sli4_hba.hdr_rq; | ||
2078 | goto pass_check; | ||
2079 | } | ||
2080 | /* DAT queue */ | ||
2081 | if (phba->sli4_hba.dat_rq->queue_id == queid) { | ||
2082 | /* Sanity check */ | ||
2083 | rc = lpfc_idiag_que_param_check( | ||
2084 | phba->sli4_hba.dat_rq, index, count); | ||
2085 | if (rc) | ||
2086 | goto error_out; | ||
2087 | idiag.ptr_private = phba->sli4_hba.dat_rq; | ||
2088 | goto pass_check; | ||
2089 | } | ||
2090 | goto error_out; | ||
2091 | break; | ||
2092 | default: | ||
2093 | goto error_out; | ||
2094 | break; | ||
2095 | } | ||
2096 | |||
2097 | pass_check: | ||
2098 | |||
2099 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) { | ||
2100 | if (count == LPFC_QUE_ACC_BROWSE) | ||
2101 | idiag.offset.last_rd = index; | ||
2102 | } | ||
2103 | |||
2104 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR || | ||
2105 | idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST || | ||
2106 | idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) { | ||
2107 | /* Additional sanity checks on write operation */ | ||
2108 | pque = (struct lpfc_queue *)idiag.ptr_private; | ||
2109 | if (offset > pque->entry_size/sizeof(uint32_t) - 1) | ||
2110 | goto error_out; | ||
2111 | pentry = pque->qe[index].address; | ||
2112 | pentry += offset; | ||
2113 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR) | ||
2114 | *pentry = value; | ||
2115 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST) | ||
2116 | *pentry |= value; | ||
2117 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) | ||
2118 | *pentry &= ~value; | ||
2119 | } | ||
2120 | return nbytes; | ||
2121 | |||
2122 | error_out: | ||
2123 | /* Clean out command structure on command error out */ | ||
2124 | memset(&idiag, 0, sizeof(idiag)); | ||
2125 | return -EINVAL; | ||
2126 | } | ||
2127 | |||
2128 | /** | ||
2129 | * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register | ||
2130 | * @phba: The pointer to hba structure. | ||
2131 | * @pbuffer: The pointer to the buffer to copy the data to. | ||
2132 | * @len: The lenght of bytes to copied. | ||
2133 | * @drbregid: The id to doorbell registers. | ||
2134 | * | ||
2135 | * Description: | ||
2136 | * This routine reads a doorbell register and copies its content to the | ||
2137 | * user buffer pointed to by @pbuffer. | ||
2138 | * | ||
2139 | * Returns: | ||
2140 | * This function returns the amount of data that was copied into @pbuffer. | ||
2141 | **/ | ||
2142 | static int | ||
2143 | lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer, | ||
2144 | int len, uint32_t drbregid) | ||
2145 | { | ||
2146 | |||
2147 | if (!pbuffer) | ||
2148 | return 0; | ||
2149 | |||
2150 | switch (drbregid) { | ||
2151 | case LPFC_DRB_EQCQ: | ||
2152 | len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, | ||
2153 | "EQCQ-DRB-REG: 0x%08x\n", | ||
2154 | readl(phba->sli4_hba.EQCQDBregaddr)); | ||
2155 | break; | ||
2156 | case LPFC_DRB_MQ: | ||
2157 | len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, | ||
2158 | "MQ-DRB-REG: 0x%08x\n", | ||
2159 | readl(phba->sli4_hba.MQDBregaddr)); | ||
2160 | break; | ||
2161 | case LPFC_DRB_WQ: | ||
2162 | len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, | ||
2163 | "WQ-DRB-REG: 0x%08x\n", | ||
2164 | readl(phba->sli4_hba.WQDBregaddr)); | ||
2165 | break; | ||
2166 | case LPFC_DRB_RQ: | ||
2167 | len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len, | ||
2168 | "RQ-DRB-REG: 0x%08x\n", | ||
2169 | readl(phba->sli4_hba.RQDBregaddr)); | ||
2170 | break; | ||
2171 | default: | ||
2172 | break; | ||
2173 | } | ||
2174 | |||
2175 | return len; | ||
2176 | } | ||
2177 | |||
2178 | /** | ||
2179 | * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell | ||
2180 | * @file: The file pointer to read from. | ||
2181 | * @buf: The buffer to copy the data to. | ||
2182 | * @nbytes: The number of bytes to read. | ||
2183 | * @ppos: The position in the file to start reading from. | ||
2184 | * | ||
2185 | * Description: | ||
2186 | * This routine reads data from the @phba device doorbell register according | ||
2187 | * to the idiag command, and copies to user @buf. Depending on the doorbell | ||
2188 | * register read command setup, it does either a single doorbell register | ||
2189 | * read or dump all doorbell registers. | ||
2190 | * | ||
2191 | * Returns: | ||
2192 | * This function returns the amount of data that was read (this could be less | ||
2193 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
2194 | **/ | ||
2195 | static ssize_t | ||
2196 | lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes, | ||
2197 | loff_t *ppos) | ||
2198 | { | ||
2199 | struct lpfc_debug *debug = file->private_data; | ||
2200 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
2201 | uint32_t drb_reg_id, i; | ||
2202 | char *pbuffer; | ||
2203 | int len = 0; | ||
2204 | |||
2205 | /* This is a user read operation */ | ||
2206 | debug->op = LPFC_IDIAG_OP_RD; | ||
2207 | |||
2208 | if (!debug->buffer) | ||
2209 | debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL); | ||
2210 | if (!debug->buffer) | ||
2211 | return 0; | ||
2212 | pbuffer = debug->buffer; | ||
2213 | |||
2214 | if (*ppos) | ||
2215 | return 0; | ||
2216 | |||
2217 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) | ||
2218 | drb_reg_id = idiag.cmd.data[0]; | ||
2219 | else | ||
2220 | return 0; | ||
2221 | |||
2222 | if (drb_reg_id == LPFC_DRB_ACC_ALL) | ||
2223 | for (i = 1; i <= LPFC_DRB_MAX; i++) | ||
2224 | len = lpfc_idiag_drbacc_read_reg(phba, | ||
2225 | pbuffer, len, i); | ||
2226 | else | ||
2227 | len = lpfc_idiag_drbacc_read_reg(phba, | ||
2228 | pbuffer, len, drb_reg_id); | ||
2229 | |||
2230 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
2231 | } | ||
2232 | |||
2233 | /** | ||
2234 | * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands | ||
2235 | * @file: The file pointer to read from. | ||
2236 | * @buf: The buffer to copy the user data from. | ||
2237 | * @nbytes: The number of bytes to get. | ||
2238 | * @ppos: The position in the file to start reading from. | ||
2239 | * | ||
2240 | * This routine get the debugfs idiag command struct from user space and then | ||
2241 | * perform the syntax check for port doorbell register read (dump) or write | ||
2242 | * (set) command accordingly. In the case of port queue read command, it sets | ||
2243 | * up the command in the idiag command struct for the following debugfs read | ||
2244 | * operation. In the case of port doorbell register write operation, it | ||
2245 | * executes the write operation into the port doorbell register accordingly. | ||
2246 | * | ||
2247 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
2248 | * In case of error conditions, it returns proper error code back to the user | ||
2249 | * space. | ||
2250 | **/ | ||
2251 | static ssize_t | ||
2252 | lpfc_idiag_drbacc_write(struct file *file, const char __user *buf, | ||
2253 | size_t nbytes, loff_t *ppos) | ||
2254 | { | ||
2255 | struct lpfc_debug *debug = file->private_data; | ||
2256 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
2257 | uint32_t drb_reg_id, value, reg_val; | ||
2258 | void __iomem *drb_reg; | ||
2259 | int rc; | ||
2260 | |||
2261 | /* This is a user write operation */ | ||
2262 | debug->op = LPFC_IDIAG_OP_WR; | ||
2263 | |||
2264 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
2265 | if (rc < 0) | ||
2266 | return rc; | ||
2267 | |||
2268 | /* Sanity check on command line arguments */ | ||
2269 | drb_reg_id = idiag.cmd.data[0]; | ||
2270 | value = idiag.cmd.data[1]; | ||
2271 | |||
2272 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || | ||
2273 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || | ||
2274 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { | ||
2275 | if (rc != LPFC_DRB_ACC_WR_CMD_ARG) | ||
2276 | goto error_out; | ||
2277 | if (drb_reg_id > LPFC_DRB_MAX) | ||
2278 | goto error_out; | ||
2279 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) { | ||
2280 | if (rc != LPFC_DRB_ACC_RD_CMD_ARG) | ||
2281 | goto error_out; | ||
2282 | if ((drb_reg_id > LPFC_DRB_MAX) && | ||
2283 | (drb_reg_id != LPFC_DRB_ACC_ALL)) | ||
2284 | goto error_out; | ||
2285 | } else | ||
2286 | goto error_out; | ||
2287 | |||
2288 | /* Perform the write access operation */ | ||
2289 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR || | ||
2290 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST || | ||
2291 | idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { | ||
2292 | switch (drb_reg_id) { | ||
2293 | case LPFC_DRB_EQCQ: | ||
2294 | drb_reg = phba->sli4_hba.EQCQDBregaddr; | ||
2295 | break; | ||
2296 | case LPFC_DRB_MQ: | ||
2297 | drb_reg = phba->sli4_hba.MQDBregaddr; | ||
2298 | break; | ||
2299 | case LPFC_DRB_WQ: | ||
2300 | drb_reg = phba->sli4_hba.WQDBregaddr; | ||
2301 | break; | ||
2302 | case LPFC_DRB_RQ: | ||
2303 | drb_reg = phba->sli4_hba.RQDBregaddr; | ||
2304 | break; | ||
2305 | default: | ||
2306 | goto error_out; | ||
2307 | } | ||
2308 | |||
2309 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR) | ||
2310 | reg_val = value; | ||
2311 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) { | ||
2312 | reg_val = readl(drb_reg); | ||
2313 | reg_val |= value; | ||
2314 | } | ||
2315 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) { | ||
2316 | reg_val = readl(drb_reg); | ||
2317 | reg_val &= ~value; | ||
2318 | } | ||
2319 | writel(reg_val, drb_reg); | ||
2320 | readl(drb_reg); /* flush */ | ||
2321 | } | ||
2322 | return nbytes; | ||
2323 | |||
2324 | error_out: | ||
2325 | /* Clean out command structure on command error out */ | ||
2326 | memset(&idiag, 0, sizeof(idiag)); | ||
2327 | return -EINVAL; | ||
2328 | } | ||
2329 | |||
1891 | #undef lpfc_debugfs_op_disc_trc | 2330 | #undef lpfc_debugfs_op_disc_trc |
1892 | static const struct file_operations lpfc_debugfs_op_disc_trc = { | 2331 | static const struct file_operations lpfc_debugfs_op_disc_trc = { |
1893 | .owner = THIS_MODULE, | 2332 | .owner = THIS_MODULE, |
@@ -1986,6 +2425,26 @@ static const struct file_operations lpfc_idiag_op_queInfo = { | |||
1986 | .release = lpfc_idiag_release, | 2425 | .release = lpfc_idiag_release, |
1987 | }; | 2426 | }; |
1988 | 2427 | ||
2428 | #undef lpfc_idiag_op_queacc | ||
2429 | static const struct file_operations lpfc_idiag_op_queAcc = { | ||
2430 | .owner = THIS_MODULE, | ||
2431 | .open = lpfc_idiag_open, | ||
2432 | .llseek = lpfc_debugfs_lseek, | ||
2433 | .read = lpfc_idiag_queacc_read, | ||
2434 | .write = lpfc_idiag_queacc_write, | ||
2435 | .release = lpfc_idiag_cmd_release, | ||
2436 | }; | ||
2437 | |||
2438 | #undef lpfc_idiag_op_drbacc | ||
2439 | static const struct file_operations lpfc_idiag_op_drbAcc = { | ||
2440 | .owner = THIS_MODULE, | ||
2441 | .open = lpfc_idiag_open, | ||
2442 | .llseek = lpfc_debugfs_lseek, | ||
2443 | .read = lpfc_idiag_drbacc_read, | ||
2444 | .write = lpfc_idiag_drbacc_write, | ||
2445 | .release = lpfc_idiag_cmd_release, | ||
2446 | }; | ||
2447 | |||
1989 | #endif | 2448 | #endif |
1990 | 2449 | ||
1991 | /** | 2450 | /** |
@@ -2261,6 +2720,32 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
2261 | } | 2720 | } |
2262 | } | 2721 | } |
2263 | 2722 | ||
2723 | /* iDiag access PCI function queue */ | ||
2724 | snprintf(name, sizeof(name), "queAcc"); | ||
2725 | if (!phba->idiag_que_acc) { | ||
2726 | phba->idiag_que_acc = | ||
2727 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
2728 | phba->idiag_root, phba, &lpfc_idiag_op_queAcc); | ||
2729 | if (!phba->idiag_que_acc) { | ||
2730 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2731 | "2926 Can't create idiag debugfs\n"); | ||
2732 | goto debug_failed; | ||
2733 | } | ||
2734 | } | ||
2735 | |||
2736 | /* iDiag access PCI function doorbell registers */ | ||
2737 | snprintf(name, sizeof(name), "drbAcc"); | ||
2738 | if (!phba->idiag_drb_acc) { | ||
2739 | phba->idiag_drb_acc = | ||
2740 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
2741 | phba->idiag_root, phba, &lpfc_idiag_op_drbAcc); | ||
2742 | if (!phba->idiag_drb_acc) { | ||
2743 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2744 | "2927 Can't create idiag debugfs\n"); | ||
2745 | goto debug_failed; | ||
2746 | } | ||
2747 | } | ||
2748 | |||
2264 | debug_failed: | 2749 | debug_failed: |
2265 | return; | 2750 | return; |
2266 | #endif | 2751 | #endif |
@@ -2339,6 +2824,16 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
2339 | * iDiag release | 2824 | * iDiag release |
2340 | */ | 2825 | */ |
2341 | if (phba->sli_rev == LPFC_SLI_REV4) { | 2826 | if (phba->sli_rev == LPFC_SLI_REV4) { |
2827 | if (phba->idiag_drb_acc) { | ||
2828 | /* iDiag drbAcc */ | ||
2829 | debugfs_remove(phba->idiag_drb_acc); | ||
2830 | phba->idiag_drb_acc = NULL; | ||
2831 | } | ||
2832 | if (phba->idiag_que_acc) { | ||
2833 | /* iDiag queAcc */ | ||
2834 | debugfs_remove(phba->idiag_que_acc); | ||
2835 | phba->idiag_que_acc = NULL; | ||
2836 | } | ||
2342 | if (phba->idiag_que_info) { | 2837 | if (phba->idiag_que_info) { |
2343 | /* iDiag queInfo */ | 2838 | /* iDiag queInfo */ |
2344 | debugfs_remove(phba->idiag_que_info); | 2839 | debugfs_remove(phba->idiag_que_info); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 91b9a9427cda..6525a5e62d27 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h | |||
@@ -39,13 +39,42 @@ | |||
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 | /* rdPciConf output buffer size */ | 42 | /* pciConf */ |
43 | #define LPFC_PCI_CFG_BROWSE 0xffff | ||
44 | #define LPFC_PCI_CFG_RD_CMD_ARG 2 | ||
45 | #define LPFC_PCI_CFG_WR_CMD_ARG 3 | ||
43 | #define LPFC_PCI_CFG_SIZE 4096 | 46 | #define LPFC_PCI_CFG_SIZE 4096 |
44 | #define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) | 47 | #define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) |
45 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) | 48 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) |
46 | 49 | ||
47 | /* queue info output buffer size */ | 50 | /* queue info */ |
48 | #define LPFC_QUE_INFO_GET_BUF_SIZE 2048 | 51 | #define LPFC_QUE_INFO_GET_BUF_SIZE 4096 |
52 | |||
53 | /* queue acc */ | ||
54 | #define LPFC_QUE_ACC_BROWSE 0xffff | ||
55 | #define LPFC_QUE_ACC_RD_CMD_ARG 4 | ||
56 | #define LPFC_QUE_ACC_WR_CMD_ARG 6 | ||
57 | #define LPFC_QUE_ACC_BUF_SIZE 4096 | ||
58 | #define LPFC_QUE_ACC_SIZE (LPFC_QUE_ACC_BUF_SIZE/2) | ||
59 | |||
60 | #define LPFC_IDIAG_EQ 1 | ||
61 | #define LPFC_IDIAG_CQ 2 | ||
62 | #define LPFC_IDIAG_MQ 3 | ||
63 | #define LPFC_IDIAG_WQ 4 | ||
64 | #define LPFC_IDIAG_RQ 5 | ||
65 | |||
66 | /* doorbell acc */ | ||
67 | #define LPFC_DRB_ACC_ALL 0xffff | ||
68 | #define LPFC_DRB_ACC_RD_CMD_ARG 1 | ||
69 | #define LPFC_DRB_ACC_WR_CMD_ARG 2 | ||
70 | #define LPFC_DRB_ACC_BUF_SIZE 256 | ||
71 | |||
72 | #define LPFC_DRB_EQCQ 1 | ||
73 | #define LPFC_DRB_MQ 2 | ||
74 | #define LPFC_DRB_WQ 3 | ||
75 | #define LPFC_DRB_RQ 4 | ||
76 | |||
77 | #define LPFC_DRB_MAX 4 | ||
49 | 78 | ||
50 | #define SIZE_U8 sizeof(uint8_t) | 79 | #define SIZE_U8 sizeof(uint8_t) |
51 | #define SIZE_U16 sizeof(uint16_t) | 80 | #define SIZE_U16 sizeof(uint16_t) |
@@ -73,13 +102,23 @@ struct lpfc_idiag_offset { | |||
73 | uint32_t last_rd; | 102 | uint32_t last_rd; |
74 | }; | 103 | }; |
75 | 104 | ||
76 | #define LPFC_IDIAG_CMD_DATA_SIZE 4 | 105 | #define LPFC_IDIAG_CMD_DATA_SIZE 8 |
77 | struct lpfc_idiag_cmd { | 106 | struct lpfc_idiag_cmd { |
78 | uint32_t opcode; | 107 | uint32_t opcode; |
79 | #define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001 | 108 | #define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001 |
80 | #define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002 | 109 | #define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002 |
81 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 | 110 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 |
82 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 | 111 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 |
112 | |||
113 | #define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011 | ||
114 | #define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012 | ||
115 | #define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013 | ||
116 | #define LPFC_IDIAG_CMD_QUEACC_CL 0x00000014 | ||
117 | |||
118 | #define LPFC_IDIAG_CMD_DRBACC_RD 0x00000021 | ||
119 | #define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022 | ||
120 | #define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023 | ||
121 | #define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024 | ||
83 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; | 122 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; |
84 | }; | 123 | }; |
85 | 124 | ||
@@ -87,6 +126,7 @@ struct lpfc_idiag { | |||
87 | uint32_t active; | 126 | uint32_t active; |
88 | struct lpfc_idiag_cmd cmd; | 127 | struct lpfc_idiag_cmd cmd; |
89 | struct lpfc_idiag_offset offset; | 128 | struct lpfc_idiag_offset offset; |
129 | void *ptr_private; | ||
90 | }; | 130 | }; |
91 | #endif | 131 | #endif |
92 | 132 | ||
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index d34b69f9cdb1..e2c452467c8b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -670,6 +670,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
670 | * Driver needs to re-reg VPI in order for f/w | 670 | * Driver needs to re-reg VPI in order for f/w |
671 | * to update the MAC address. | 671 | * to update the MAC address. |
672 | */ | 672 | */ |
673 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
673 | lpfc_register_new_vport(phba, vport, ndlp); | 674 | lpfc_register_new_vport(phba, vport, ndlp); |
674 | return 0; | 675 | return 0; |
675 | } | 676 | } |
@@ -869,8 +870,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
869 | */ | 870 | */ |
870 | if ((phba->hba_flag & HBA_FIP_SUPPORT) && | 871 | if ((phba->hba_flag & HBA_FIP_SUPPORT) && |
871 | (phba->fcf.fcf_flag & FCF_DISCOVERY) && | 872 | (phba->fcf.fcf_flag & FCF_DISCOVERY) && |
872 | (irsp->ulpStatus != IOSTAT_LOCAL_REJECT) && | 873 | !((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && |
873 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { | 874 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) { |
874 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, | 875 | lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, |
875 | "2611 FLOGI failed on FCF (x%x), " | 876 | "2611 FLOGI failed on FCF (x%x), " |
876 | "status:x%x/x%x, tmo:x%x, perform " | 877 | "status:x%x/x%x, tmo:x%x, perform " |
@@ -1085,14 +1086,15 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1085 | if (sp->cmn.fcphHigh < FC_PH3) | 1086 | if (sp->cmn.fcphHigh < FC_PH3) |
1086 | sp->cmn.fcphHigh = FC_PH3; | 1087 | sp->cmn.fcphHigh = FC_PH3; |
1087 | 1088 | ||
1088 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 1089 | if (phba->sli_rev == LPFC_SLI_REV4) { |
1089 | (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == | 1090 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == |
1090 | LPFC_SLI_INTF_IF_TYPE_0)) { | 1091 | LPFC_SLI_INTF_IF_TYPE_0) { |
1091 | elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1); | 1092 | elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1); |
1092 | elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1); | 1093 | elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1); |
1093 | /* FLOGI needs to be 3 for WQE FCFI */ | 1094 | /* FLOGI needs to be 3 for WQE FCFI */ |
1094 | /* Set the fcfi to the fcfi we registered with */ | 1095 | /* Set the fcfi to the fcfi we registered with */ |
1095 | elsiocb->iocb.ulpContext = phba->fcf.fcfi; | 1096 | elsiocb->iocb.ulpContext = phba->fcf.fcfi; |
1097 | } | ||
1096 | } else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 1098 | } else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
1097 | sp->cmn.request_multiple_Nport = 1; | 1099 | sp->cmn.request_multiple_Nport = 1; |
1098 | /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */ | 1100 | /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */ |
@@ -4107,13 +4109,13 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport, | |||
4107 | pcmd += sizeof(uint32_t); | 4109 | pcmd += sizeof(uint32_t); |
4108 | rrq = (struct RRQ *)pcmd; | 4110 | rrq = (struct RRQ *)pcmd; |
4109 | rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg); | 4111 | rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg); |
4110 | rxid = be16_to_cpu(bf_get(rrq_rxid, rrq)); | 4112 | rxid = bf_get(rrq_rxid, rrq); |
4111 | 4113 | ||
4112 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 4114 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
4113 | "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" | 4115 | "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" |
4114 | " x%x x%x\n", | 4116 | " x%x x%x\n", |
4115 | be32_to_cpu(bf_get(rrq_did, rrq)), | 4117 | be32_to_cpu(bf_get(rrq_did, rrq)), |
4116 | be16_to_cpu(bf_get(rrq_oxid, rrq)), | 4118 | bf_get(rrq_oxid, rrq), |
4117 | rxid, | 4119 | rxid, |
4118 | iocb->iotag, iocb->iocb.ulpContext); | 4120 | iocb->iotag, iocb->iocb.ulpContext); |
4119 | 4121 | ||
@@ -4121,7 +4123,7 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport, | |||
4121 | "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", | 4123 | "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", |
4122 | ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); | 4124 | ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); |
4123 | if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq))) | 4125 | if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq))) |
4124 | xri = be16_to_cpu(bf_get(rrq_oxid, rrq)); | 4126 | xri = bf_get(rrq_oxid, rrq); |
4125 | else | 4127 | else |
4126 | xri = rxid; | 4128 | xri = rxid; |
4127 | prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID); | 4129 | prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID); |
@@ -7290,8 +7292,9 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7290 | struct lpfc_vport *vport = cmdiocb->vport; | 7292 | struct lpfc_vport *vport = cmdiocb->vport; |
7291 | IOCB_t *irsp; | 7293 | IOCB_t *irsp; |
7292 | struct lpfc_nodelist *ndlp; | 7294 | struct lpfc_nodelist *ndlp; |
7293 | ndlp = (struct lpfc_nodelist *)cmdiocb->context1; | 7295 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
7294 | 7296 | ||
7297 | ndlp = (struct lpfc_nodelist *)cmdiocb->context1; | ||
7295 | irsp = &rspiocb->iocb; | 7298 | irsp = &rspiocb->iocb; |
7296 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | 7299 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
7297 | "LOGO npiv cmpl: status:x%x/x%x did:x%x", | 7300 | "LOGO npiv cmpl: status:x%x/x%x did:x%x", |
@@ -7302,6 +7305,19 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
7302 | 7305 | ||
7303 | /* Trigger the release of the ndlp after logo */ | 7306 | /* Trigger the release of the ndlp after logo */ |
7304 | lpfc_nlp_put(ndlp); | 7307 | lpfc_nlp_put(ndlp); |
7308 | |||
7309 | /* NPIV LOGO completes to NPort <nlp_DID> */ | ||
7310 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
7311 | "2928 NPIV LOGO completes to NPort x%x " | ||
7312 | "Data: x%x x%x x%x x%x\n", | ||
7313 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], | ||
7314 | irsp->ulpTimeout, vport->num_disc_nodes); | ||
7315 | |||
7316 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { | ||
7317 | spin_lock_irq(shost->host_lock); | ||
7318 | vport->fc_flag &= ~FC_FABRIC; | ||
7319 | spin_unlock_irq(shost->host_lock); | ||
7320 | } | ||
7305 | } | 7321 | } |
7306 | 7322 | ||
7307 | /** | 7323 | /** |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 301498301a8f..7a35df5e2038 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2009 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -3569,6 +3569,10 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
3569 | "rport add: did:x%x flg:x%x type x%x", | 3569 | "rport add: did:x%x flg:x%x type x%x", |
3570 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | 3570 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); |
3571 | 3571 | ||
3572 | /* Don't add the remote port if unloading. */ | ||
3573 | if (vport->load_flag & FC_UNLOADING) | ||
3574 | return; | ||
3575 | |||
3572 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); | 3576 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); |
3573 | if (!rport || !get_device(&rport->dev)) { | 3577 | if (!rport || !get_device(&rport->dev)) { |
3574 | dev_printk(KERN_WARNING, &phba->pcidev->dev, | 3578 | dev_printk(KERN_WARNING, &phba->pcidev->dev, |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 8433ac0d9fb4..4dff668ebdad 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -1059,6 +1059,11 @@ struct rq_context { | |||
1059 | #define lpfc_rq_context_rqe_size_SHIFT 8 /* Version 1 Only */ | 1059 | #define lpfc_rq_context_rqe_size_SHIFT 8 /* Version 1 Only */ |
1060 | #define lpfc_rq_context_rqe_size_MASK 0x0000000F | 1060 | #define lpfc_rq_context_rqe_size_MASK 0x0000000F |
1061 | #define lpfc_rq_context_rqe_size_WORD word0 | 1061 | #define lpfc_rq_context_rqe_size_WORD word0 |
1062 | #define LPFC_RQE_SIZE_8 2 | ||
1063 | #define LPFC_RQE_SIZE_16 3 | ||
1064 | #define LPFC_RQE_SIZE_32 4 | ||
1065 | #define LPFC_RQE_SIZE_64 5 | ||
1066 | #define LPFC_RQE_SIZE_128 6 | ||
1062 | #define lpfc_rq_context_page_size_SHIFT 0 /* Version 1 Only */ | 1067 | #define lpfc_rq_context_page_size_SHIFT 0 /* Version 1 Only */ |
1063 | #define lpfc_rq_context_page_size_MASK 0x000000FF | 1068 | #define lpfc_rq_context_page_size_MASK 0x000000FF |
1064 | #define lpfc_rq_context_page_size_WORD word0 | 1069 | #define lpfc_rq_context_page_size_WORD word0 |
@@ -2108,6 +2113,8 @@ struct lpfc_mbx_pc_sli4_params { | |||
2108 | #define sgl_pp_align_WORD word12 | 2113 | #define sgl_pp_align_WORD word12 |
2109 | uint32_t rsvd_13_63[51]; | 2114 | uint32_t rsvd_13_63[51]; |
2110 | }; | 2115 | }; |
2116 | #define SLI4_PAGE_ALIGN(addr) (((addr)+((SLI4_PAGE_SIZE)-1)) \ | ||
2117 | &(~((SLI4_PAGE_SIZE)-1))) | ||
2111 | 2118 | ||
2112 | struct lpfc_sli4_parameters { | 2119 | struct lpfc_sli4_parameters { |
2113 | uint32_t word0; | 2120 | uint32_t word0; |
@@ -2491,6 +2498,9 @@ struct wqe_common { | |||
2491 | #define wqe_reqtag_SHIFT 0 | 2498 | #define wqe_reqtag_SHIFT 0 |
2492 | #define wqe_reqtag_MASK 0x0000FFFF | 2499 | #define wqe_reqtag_MASK 0x0000FFFF |
2493 | #define wqe_reqtag_WORD word9 | 2500 | #define wqe_reqtag_WORD word9 |
2501 | #define wqe_temp_rpi_SHIFT 16 | ||
2502 | #define wqe_temp_rpi_MASK 0x0000FFFF | ||
2503 | #define wqe_temp_rpi_WORD word9 | ||
2494 | #define wqe_rcvoxid_SHIFT 16 | 2504 | #define wqe_rcvoxid_SHIFT 16 |
2495 | #define wqe_rcvoxid_MASK 0x0000FFFF | 2505 | #define wqe_rcvoxid_MASK 0x0000FFFF |
2496 | #define wqe_rcvoxid_WORD word9 | 2506 | #define wqe_rcvoxid_WORD word9 |
@@ -2524,7 +2534,7 @@ struct wqe_common { | |||
2524 | #define wqe_wqes_WORD word10 | 2534 | #define wqe_wqes_WORD word10 |
2525 | /* Note that this field overlaps above fields */ | 2535 | /* Note that this field overlaps above fields */ |
2526 | #define wqe_wqid_SHIFT 1 | 2536 | #define wqe_wqid_SHIFT 1 |
2527 | #define wqe_wqid_MASK 0x0000007f | 2537 | #define wqe_wqid_MASK 0x00007fff |
2528 | #define wqe_wqid_WORD word10 | 2538 | #define wqe_wqid_WORD word10 |
2529 | #define wqe_pri_SHIFT 16 | 2539 | #define wqe_pri_SHIFT 16 |
2530 | #define wqe_pri_MASK 0x00000007 | 2540 | #define wqe_pri_MASK 0x00000007 |
@@ -2621,7 +2631,11 @@ struct xmit_els_rsp64_wqe { | |||
2621 | uint32_t rsvd4; | 2631 | uint32_t rsvd4; |
2622 | struct wqe_did wqe_dest; | 2632 | struct wqe_did wqe_dest; |
2623 | struct wqe_common wqe_com; /* words 6-11 */ | 2633 | struct wqe_common wqe_com; /* words 6-11 */ |
2624 | uint32_t rsvd_12_15[4]; | 2634 | uint32_t word12; |
2635 | #define wqe_rsp_temp_rpi_SHIFT 0 | ||
2636 | #define wqe_rsp_temp_rpi_MASK 0x0000FFFF | ||
2637 | #define wqe_rsp_temp_rpi_WORD word12 | ||
2638 | uint32_t rsvd_13_15[3]; | ||
2625 | }; | 2639 | }; |
2626 | 2640 | ||
2627 | struct xmit_bls_rsp64_wqe { | 2641 | struct xmit_bls_rsp64_wqe { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 505f88443b5c..7dda036a1af3 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -3209,9 +3209,9 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, | |||
3209 | phba->sli4_hba.link_state.logical_speed = | 3209 | phba->sli4_hba.link_state.logical_speed = |
3210 | bf_get(lpfc_acqe_logical_link_speed, acqe_link); | 3210 | bf_get(lpfc_acqe_logical_link_speed, acqe_link); |
3211 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 3211 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
3212 | "2900 Async FCoE Link event - Speed:%dGBit duplex:x%x " | 3212 | "2900 Async FC/FCoE Link event - Speed:%dGBit " |
3213 | "LA Type:x%x Port Type:%d Port Number:%d Logical " | 3213 | "duplex:x%x LA Type:x%x Port Type:%d Port Number:%d " |
3214 | "speed:%dMbps Fault:%d\n", | 3214 | "Logical speed:%dMbps Fault:%d\n", |
3215 | phba->sli4_hba.link_state.speed, | 3215 | phba->sli4_hba.link_state.speed, |
3216 | phba->sli4_hba.link_state.topology, | 3216 | phba->sli4_hba.link_state.topology, |
3217 | phba->sli4_hba.link_state.status, | 3217 | phba->sli4_hba.link_state.status, |
@@ -4906,6 +4906,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4906 | uint16_t rpi_limit, curr_rpi_range; | 4906 | uint16_t rpi_limit, curr_rpi_range; |
4907 | struct lpfc_dmabuf *dmabuf; | 4907 | struct lpfc_dmabuf *dmabuf; |
4908 | struct lpfc_rpi_hdr *rpi_hdr; | 4908 | struct lpfc_rpi_hdr *rpi_hdr; |
4909 | uint32_t rpi_count; | ||
4909 | 4910 | ||
4910 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + | 4911 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + |
4911 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | 4912 | phba->sli4_hba.max_cfg_param.max_rpi - 1; |
@@ -4920,7 +4921,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4920 | * and to allow the full max_rpi range per port. | 4921 | * and to allow the full max_rpi range per port. |
4921 | */ | 4922 | */ |
4922 | if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit) | 4923 | if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit) |
4923 | return NULL; | 4924 | rpi_count = rpi_limit - curr_rpi_range; |
4925 | else | ||
4926 | rpi_count = LPFC_RPI_HDR_COUNT; | ||
4924 | 4927 | ||
4925 | /* | 4928 | /* |
4926 | * First allocate the protocol header region for the port. The | 4929 | * First allocate the protocol header region for the port. The |
@@ -4961,7 +4964,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
4961 | * The next_rpi stores the next module-64 rpi value to post | 4964 | * The next_rpi stores the next module-64 rpi value to post |
4962 | * in any subsequent rpi memory region postings. | 4965 | * in any subsequent rpi memory region postings. |
4963 | */ | 4966 | */ |
4964 | phba->sli4_hba.next_rpi += LPFC_RPI_HDR_COUNT; | 4967 | phba->sli4_hba.next_rpi += rpi_count; |
4965 | spin_unlock_irq(&phba->hbalock); | 4968 | spin_unlock_irq(&phba->hbalock); |
4966 | return rpi_hdr; | 4969 | return rpi_hdr; |
4967 | 4970 | ||
@@ -7004,7 +7007,8 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) | |||
7004 | lpfc_sli4_bar0_register_memmap(phba, if_type); | 7007 | lpfc_sli4_bar0_register_memmap(phba, if_type); |
7005 | } | 7008 | } |
7006 | 7009 | ||
7007 | if (pci_resource_start(pdev, 2)) { | 7010 | if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) && |
7011 | (pci_resource_start(pdev, 2))) { | ||
7008 | /* | 7012 | /* |
7009 | * Map SLI4 if type 0 HBA Control Register base to a kernel | 7013 | * Map SLI4 if type 0 HBA Control Register base to a kernel |
7010 | * virtual address and setup the registers. | 7014 | * virtual address and setup the registers. |
@@ -7021,7 +7025,8 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) | |||
7021 | lpfc_sli4_bar1_register_memmap(phba); | 7025 | lpfc_sli4_bar1_register_memmap(phba); |
7022 | } | 7026 | } |
7023 | 7027 | ||
7024 | if (pci_resource_start(pdev, 4)) { | 7028 | if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) && |
7029 | (pci_resource_start(pdev, 4))) { | ||
7025 | /* | 7030 | /* |
7026 | * Map SLI4 if type 0 HBA Doorbell Register base to a kernel | 7031 | * Map SLI4 if type 0 HBA Doorbell Register base to a kernel |
7027 | * virtual address and setup the registers. | 7032 | * virtual address and setup the registers. |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index fbab9734e9b4..e6ce9033f85e 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1736,7 +1736,7 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | |||
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | /* Setup for the none-embedded mbox command */ | 1738 | /* Setup for the none-embedded mbox command */ |
1739 | pcount = (PAGE_ALIGN(length))/SLI4_PAGE_SIZE; | 1739 | pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE; |
1740 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? | 1740 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? |
1741 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; | 1741 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; |
1742 | /* Allocate record for keeping SGE virtual addresses */ | 1742 | /* Allocate record for keeping SGE virtual addresses */ |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fe7cc84e773b..84e4481b2406 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -3238,9 +3238,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
3238 | if (!lpfc_cmd) { | 3238 | if (!lpfc_cmd) { |
3239 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 3239 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
3240 | "2873 SCSI Layer I/O Abort Request IO CMPL Status " | 3240 | "2873 SCSI Layer I/O Abort Request IO CMPL Status " |
3241 | "x%x ID %d " | 3241 | "x%x ID %d LUN %d\n", |
3242 | "LUN %d snum %#lx\n", ret, cmnd->device->id, | 3242 | ret, cmnd->device->id, cmnd->device->lun); |
3243 | cmnd->device->lun, cmnd->serial_number); | ||
3244 | return SUCCESS; | 3243 | return SUCCESS; |
3245 | } | 3244 | } |
3246 | 3245 | ||
@@ -3318,16 +3317,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
3318 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 3317 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
3319 | "0748 abort handler timed out waiting " | 3318 | "0748 abort handler timed out waiting " |
3320 | "for abort to complete: ret %#x, ID %d, " | 3319 | "for abort to complete: ret %#x, ID %d, " |
3321 | "LUN %d, snum %#lx\n", | 3320 | "LUN %d\n", |
3322 | ret, cmnd->device->id, cmnd->device->lun, | 3321 | ret, cmnd->device->id, cmnd->device->lun); |
3323 | cmnd->serial_number); | ||
3324 | } | 3322 | } |
3325 | 3323 | ||
3326 | out: | 3324 | out: |
3327 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 3325 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
3328 | "0749 SCSI Layer I/O Abort Request Status x%x ID %d " | 3326 | "0749 SCSI Layer I/O Abort Request Status x%x ID %d " |
3329 | "LUN %d snum %#lx\n", ret, cmnd->device->id, | 3327 | "LUN %d\n", ret, cmnd->device->id, |
3330 | cmnd->device->lun, cmnd->serial_number); | 3328 | cmnd->device->lun); |
3331 | return ret; | 3329 | return ret; |
3332 | } | 3330 | } |
3333 | 3331 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index dacabbe0a586..837d272cb2d6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4769,8 +4769,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4769 | else | 4769 | else |
4770 | phba->hba_flag &= ~HBA_FIP_SUPPORT; | 4770 | phba->hba_flag &= ~HBA_FIP_SUPPORT; |
4771 | 4771 | ||
4772 | if (phba->sli_rev != LPFC_SLI_REV4 || | 4772 | if (phba->sli_rev != LPFC_SLI_REV4) { |
4773 | !(phba->hba_flag & HBA_FCOE_MODE)) { | ||
4774 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 4773 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
4775 | "0376 READ_REV Error. SLI Level %d " | 4774 | "0376 READ_REV Error. SLI Level %d " |
4776 | "FCoE enabled %d\n", | 4775 | "FCoE enabled %d\n", |
@@ -5018,10 +5017,11 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
5018 | lpfc_reg_fcfi(phba, mboxq); | 5017 | lpfc_reg_fcfi(phba, mboxq); |
5019 | mboxq->vport = phba->pport; | 5018 | mboxq->vport = phba->pport; |
5020 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | 5019 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); |
5021 | if (rc == MBX_SUCCESS) | 5020 | if (rc != MBX_SUCCESS) |
5022 | rc = 0; | ||
5023 | else | ||
5024 | goto out_unset_queue; | 5021 | goto out_unset_queue; |
5022 | rc = 0; | ||
5023 | phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi, | ||
5024 | &mboxq->u.mqe.un.reg_fcfi); | ||
5025 | } | 5025 | } |
5026 | /* | 5026 | /* |
5027 | * The port is ready, set the host's link state to LINK_DOWN | 5027 | * The port is ready, set the host's link state to LINK_DOWN |
@@ -6402,6 +6402,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6402 | uint32_t els_id = LPFC_ELS_ID_DEFAULT; | 6402 | uint32_t els_id = LPFC_ELS_ID_DEFAULT; |
6403 | int numBdes, i; | 6403 | int numBdes, i; |
6404 | struct ulp_bde64 bde; | 6404 | struct ulp_bde64 bde; |
6405 | struct lpfc_nodelist *ndlp; | ||
6405 | 6406 | ||
6406 | fip = phba->hba_flag & HBA_FIP_SUPPORT; | 6407 | fip = phba->hba_flag & HBA_FIP_SUPPORT; |
6407 | /* The fcp commands will set command type */ | 6408 | /* The fcp commands will set command type */ |
@@ -6447,6 +6448,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6447 | 6448 | ||
6448 | switch (iocbq->iocb.ulpCommand) { | 6449 | switch (iocbq->iocb.ulpCommand) { |
6449 | case CMD_ELS_REQUEST64_CR: | 6450 | case CMD_ELS_REQUEST64_CR: |
6451 | ndlp = (struct lpfc_nodelist *)iocbq->context1; | ||
6450 | if (!iocbq->iocb.ulpLe) { | 6452 | if (!iocbq->iocb.ulpLe) { |
6451 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 6453 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
6452 | "2007 Only Limited Edition cmd Format" | 6454 | "2007 Only Limited Edition cmd Format" |
@@ -6472,6 +6474,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6472 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) | 6474 | els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) |
6473 | >> LPFC_FIP_ELS_ID_SHIFT); | 6475 | >> LPFC_FIP_ELS_ID_SHIFT); |
6474 | } | 6476 | } |
6477 | bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, ndlp->nlp_rpi); | ||
6475 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); | 6478 | bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); |
6476 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); | 6479 | bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); |
6477 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); | 6480 | bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); |
@@ -6604,6 +6607,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6604 | command_type = OTHER_COMMAND; | 6607 | command_type = OTHER_COMMAND; |
6605 | break; | 6608 | break; |
6606 | case CMD_XMIT_ELS_RSP64_CX: | 6609 | case CMD_XMIT_ELS_RSP64_CX: |
6610 | ndlp = (struct lpfc_nodelist *)iocbq->context1; | ||
6607 | /* words0-2 BDE memcpy */ | 6611 | /* words0-2 BDE memcpy */ |
6608 | /* word3 iocb=iotag32 wqe=response_payload_len */ | 6612 | /* word3 iocb=iotag32 wqe=response_payload_len */ |
6609 | wqe->xmit_els_rsp.response_payload_len = xmit_len; | 6613 | wqe->xmit_els_rsp.response_payload_len = xmit_len; |
@@ -6626,6 +6630,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
6626 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, | 6630 | bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, |
6627 | LPFC_WQE_LENLOC_WORD3); | 6631 | LPFC_WQE_LENLOC_WORD3); |
6628 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); | 6632 | bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); |
6633 | bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, ndlp->nlp_rpi); | ||
6629 | command_type = OTHER_COMMAND; | 6634 | command_type = OTHER_COMMAND; |
6630 | break; | 6635 | break; |
6631 | case CMD_CLOSE_XRI_CN: | 6636 | case CMD_CLOSE_XRI_CN: |
@@ -10522,8 +10527,8 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
10522 | bf_set(lpfc_mbox_hdr_version, &shdr->request, | 10527 | bf_set(lpfc_mbox_hdr_version, &shdr->request, |
10523 | phba->sli4_hba.pc_sli4_params.cqv); | 10528 | phba->sli4_hba.pc_sli4_params.cqv); |
10524 | if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) { | 10529 | if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) { |
10525 | bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request, | 10530 | /* FW only supports 1. Should be PAGE_SIZE/SLI4_PAGE_SIZE */ |
10526 | (PAGE_SIZE/SLI4_PAGE_SIZE)); | 10531 | bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request, 1); |
10527 | bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context, | 10532 | bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context, |
10528 | eq->queue_id); | 10533 | eq->queue_id); |
10529 | } else { | 10534 | } else { |
@@ -10967,6 +10972,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
10967 | &rq_create->u.request.context, | 10972 | &rq_create->u.request.context, |
10968 | hrq->entry_count); | 10973 | hrq->entry_count); |
10969 | rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE; | 10974 | rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE; |
10975 | bf_set(lpfc_rq_context_rqe_size, | ||
10976 | &rq_create->u.request.context, | ||
10977 | LPFC_RQE_SIZE_8); | ||
10978 | bf_set(lpfc_rq_context_page_size, | ||
10979 | &rq_create->u.request.context, | ||
10980 | (PAGE_SIZE/SLI4_PAGE_SIZE)); | ||
10970 | } else { | 10981 | } else { |
10971 | switch (hrq->entry_count) { | 10982 | switch (hrq->entry_count) { |
10972 | default: | 10983 | default: |
@@ -11042,9 +11053,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
11042 | phba->sli4_hba.pc_sli4_params.rqv); | 11053 | phba->sli4_hba.pc_sli4_params.rqv); |
11043 | if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) { | 11054 | if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) { |
11044 | bf_set(lpfc_rq_context_rqe_count_1, | 11055 | bf_set(lpfc_rq_context_rqe_count_1, |
11045 | &rq_create->u.request.context, | 11056 | &rq_create->u.request.context, hrq->entry_count); |
11046 | hrq->entry_count); | ||
11047 | rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE; | 11057 | rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE; |
11058 | bf_set(lpfc_rq_context_rqe_size, &rq_create->u.request.context, | ||
11059 | LPFC_RQE_SIZE_8); | ||
11060 | bf_set(lpfc_rq_context_page_size, &rq_create->u.request.context, | ||
11061 | (PAGE_SIZE/SLI4_PAGE_SIZE)); | ||
11048 | } else { | 11062 | } else { |
11049 | switch (drq->entry_count) { | 11063 | switch (drq->entry_count) { |
11050 | default: | 11064 | default: |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 2404d1d65563..c03921b1232c 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.3.22" | 21 | #define LPFC_DRIVER_VERSION "8.3.23" |
22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" | 23 | #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" |
24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" | 24 | #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" |