@@ -120,6 +120,16 @@ enum ELX_LOOPBACK_CMD {
120120#define ELX_LOOPBACK_HEADER_SZ \
121121 (size_t)(&((struct lpfc_sli_ct_request *)NULL)->un)
122122
123+ /* For non-embedded read object command */
124+ #define READ_OBJ_EMB0_SCHEME_0 {1, 10, 256, 128}
125+ #define READ_OBJ_EMB0_SCHEME_1 {11, LPFC_EMB0_MAX_RD_OBJ_HBD_CNT, 512, 192}
126+ static const struct lpfc_read_object_cmd_scheme {
127+ u32 min_hbd_cnt ;
128+ u32 max_hbd_cnt ;
129+ u32 cmd_size ;
130+ u32 payload_word_offset ;
131+ } rd_obj_scheme [2 ] = {READ_OBJ_EMB0_SCHEME_0 , READ_OBJ_EMB0_SCHEME_1 };
132+
123133struct lpfc_dmabufext {
124134 struct lpfc_dmabuf dma ;
125135 uint32_t size ;
@@ -3538,6 +3548,103 @@ lpfc_bsg_mbox_ext_session_reset(struct lpfc_hba *phba)
35383548 return ;
35393549}
35403550
3551+ /**
3552+ * lpfc_rd_obj_emb0_handle_job - Handles completion for non-embedded
3553+ * READ_OBJECT_V0 mailbox commands
3554+ * @phba: pointer to lpfc_hba data struct
3555+ * @pmb_buf: pointer to mailbox buffer
3556+ * @sli_cfg_mbx: pointer to SLI_CONFIG mailbox memory region
3557+ * @job: pointer to bsg_job struct
3558+ * @bsg_reply: point to bsg_reply struct
3559+ *
3560+ * Given a non-embedded READ_OBJECT_V0's HBD_CNT, this routine copies
3561+ * a READ_OBJECT_V0 mailbox command's read data payload into a bsg_job
3562+ * structure for passing back to application layer.
3563+ *
3564+ * Return codes
3565+ * 0 - successful
3566+ * -EINVAL - invalid HBD_CNT
3567+ * -ENODEV - pointer to bsg_job struct is NULL
3568+ **/
3569+ static int
3570+ lpfc_rd_obj_emb0_handle_job (struct lpfc_hba * phba , u8 * pmb_buf ,
3571+ struct lpfc_sli_config_mbox * sli_cfg_mbx ,
3572+ struct bsg_job * job ,
3573+ struct fc_bsg_reply * bsg_reply )
3574+ {
3575+ struct lpfc_dmabuf * curr_dmabuf , * next_dmabuf ;
3576+ struct lpfc_sli_config_emb0_subsys * emb0_subsys ;
3577+ u32 hbd_cnt ;
3578+ u32 dma_buf_len ;
3579+ u8 i = 0 ;
3580+ size_t extra_bytes ;
3581+ off_t skip = 0 ;
3582+
3583+ if (!job ) {
3584+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
3585+ "2496 NULL job\n" );
3586+ return - ENODEV ;
3587+ }
3588+
3589+ if (!bsg_reply ) {
3590+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
3591+ "2498 NULL bsg_reply\n" );
3592+ return - ENODEV ;
3593+ }
3594+
3595+ emb0_subsys = & sli_cfg_mbx -> un .sli_config_emb0_subsys ;
3596+
3597+ hbd_cnt = bsg_bf_get (lpfc_emb0_subcmnd_rd_obj_hbd_cnt ,
3598+ emb0_subsys );
3599+
3600+ /* Calculate where the read object's read data payload is located based
3601+ * on HBD count scheme.
3602+ */
3603+ if (hbd_cnt >= rd_obj_scheme [0 ].min_hbd_cnt &&
3604+ hbd_cnt <= rd_obj_scheme [0 ].max_hbd_cnt ) {
3605+ skip = rd_obj_scheme [0 ].payload_word_offset * 4 ;
3606+ } else if (hbd_cnt >= rd_obj_scheme [1 ].min_hbd_cnt &&
3607+ hbd_cnt <= rd_obj_scheme [1 ].max_hbd_cnt ) {
3608+ skip = rd_obj_scheme [1 ].payload_word_offset * 4 ;
3609+ } else {
3610+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
3611+ "2497 bad hbd_count 0x%08x\n" ,
3612+ hbd_cnt );
3613+ return - EINVAL ;
3614+ }
3615+
3616+ /* Copy SLI_CONFIG command and READ_OBJECT response first */
3617+ bsg_reply -> reply_payload_rcv_len =
3618+ sg_copy_from_buffer (job -> reply_payload .sg_list ,
3619+ job -> reply_payload .sg_cnt ,
3620+ pmb_buf , skip );
3621+
3622+ /* Copy data from hbds */
3623+ list_for_each_entry_safe (curr_dmabuf , next_dmabuf ,
3624+ & phba -> mbox_ext_buf_ctx .ext_dmabuf_list ,
3625+ list ) {
3626+ dma_buf_len = emb0_subsys -> hbd [i ].buf_len ;
3627+
3628+ /* Use sg_copy_buffer to specify a skip offset */
3629+ extra_bytes = sg_copy_buffer (job -> reply_payload .sg_list ,
3630+ job -> reply_payload .sg_cnt ,
3631+ curr_dmabuf -> virt ,
3632+ dma_buf_len , skip , false);
3633+
3634+ bsg_reply -> reply_payload_rcv_len += extra_bytes ;
3635+
3636+ skip += extra_bytes ;
3637+
3638+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
3639+ "2499 copied hbd[%d] "
3640+ "0x%zx bytes\n" ,
3641+ i , extra_bytes );
3642+ i ++ ;
3643+ }
3644+
3645+ return 0 ;
3646+ }
3647+
35413648/**
35423649 * lpfc_bsg_issue_mbox_ext_handle_job - job handler for multi-buffer mbox cmpl
35433650 * @phba: Pointer to HBA context object.
@@ -3551,10 +3658,10 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
35513658{
35523659 struct bsg_job_data * dd_data ;
35533660 struct bsg_job * job ;
3554- struct fc_bsg_reply * bsg_reply ;
3661+ struct fc_bsg_reply * bsg_reply = NULL ;
35553662 uint8_t * pmb , * pmb_buf ;
35563663 unsigned long flags ;
3557- uint32_t size ;
3664+ u32 size , opcode ;
35583665 int rc = 0 ;
35593666 struct lpfc_dmabuf * dmabuf ;
35603667 struct lpfc_sli_config_mbox * sli_cfg_mbx ;
@@ -3591,6 +3698,24 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
35913698 lpfc_sli_pcimem_bcopy (& pmbx [sizeof (MAILBOX_t )],
35923699 & pmbx [sizeof (MAILBOX_t )],
35933700 sli_cfg_mbx -> un .sli_config_emb0_subsys .mse [0 ].buf_len );
3701+
3702+ /* Special handling for non-embedded READ_OBJECT */
3703+ opcode = bsg_bf_get (lpfc_emb0_subcmnd_opcode ,
3704+ & sli_cfg_mbx -> un .sli_config_emb0_subsys );
3705+ switch (opcode ) {
3706+ case COMN_OPCODE_READ_OBJECT :
3707+ if (job ) {
3708+ rc = lpfc_rd_obj_emb0_handle_job (phba , pmb_buf ,
3709+ sli_cfg_mbx ,
3710+ job ,
3711+ bsg_reply );
3712+ bsg_reply -> result = rc ;
3713+ goto done ;
3714+ }
3715+ break ;
3716+ default :
3717+ break ;
3718+ }
35943719 }
35953720
35963721 /* Complete the job if the job is still active */
@@ -3604,12 +3729,14 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
36043729
36053730 /* result for successful */
36063731 bsg_reply -> result = 0 ;
3732+ done :
36073733
36083734 lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
36093735 "2937 SLI_CONFIG ext-buffer mailbox command "
36103736 "(x%x/x%x) complete bsg job done, bsize:%d\n" ,
36113737 phba -> mbox_ext_buf_ctx .nembType ,
3612- phba -> mbox_ext_buf_ctx .mboxType , size );
3738+ phba -> mbox_ext_buf_ctx .mboxType ,
3739+ job -> reply_payload .payload_len );
36133740 lpfc_idiag_mbxacc_dump_bsg_mbox (phba ,
36143741 phba -> mbox_ext_buf_ctx .nembType ,
36153742 phba -> mbox_ext_buf_ctx .mboxType ,
@@ -3819,14 +3946,16 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
38193946{
38203947 struct fc_bsg_request * bsg_request = job -> request ;
38213948 struct lpfc_sli_config_mbox * sli_cfg_mbx ;
3949+ struct lpfc_sli_config_emb0_subsys * emb0_subsys ;
3950+ struct list_head * ext_dmabuf_list ;
38223951 struct dfc_mbox_req * mbox_req ;
38233952 struct lpfc_dmabuf * curr_dmabuf , * next_dmabuf ;
3824- uint32_t ext_buf_cnt , ext_buf_index ;
3953+ u32 ext_buf_cnt , ext_buf_index , hbd_cnt ;
38253954 struct lpfc_dmabuf * ext_dmabuf = NULL ;
38263955 struct bsg_job_data * dd_data = NULL ;
38273956 LPFC_MBOXQ_t * pmboxq = NULL ;
38283957 MAILBOX_t * pmb ;
3829- uint8_t * pmbx ;
3958+ u8 * pmbx , opcode ;
38303959 int rc , i ;
38313960
38323961 mbox_req =
@@ -3836,8 +3965,9 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
38363965 sli_cfg_mbx = (struct lpfc_sli_config_mbox * )dmabuf -> virt ;
38373966
38383967 if (nemb_tp == nemb_mse ) {
3968+ emb0_subsys = & sli_cfg_mbx -> un .sli_config_emb0_subsys ;
38393969 ext_buf_cnt = bsg_bf_get (lpfc_mbox_hdr_mse_cnt ,
3840- & sli_cfg_mbx -> un . sli_config_emb0_subsys . sli_config_hdr );
3970+ & emb0_subsys -> sli_config_hdr );
38413971 if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE ) {
38423972 lpfc_printf_log (phba , KERN_ERR , LOG_LIBDFC ,
38433973 "2945 Handled SLI_CONFIG(mse) rd, "
@@ -3847,6 +3977,57 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
38473977 rc = - ERANGE ;
38483978 goto job_error ;
38493979 }
3980+
3981+ /* Special handling for non-embedded READ_OBJECT */
3982+ opcode = bsg_bf_get (lpfc_emb0_subcmnd_opcode , emb0_subsys );
3983+ switch (opcode ) {
3984+ case COMN_OPCODE_READ_OBJECT :
3985+ hbd_cnt = bsg_bf_get (lpfc_emb0_subcmnd_rd_obj_hbd_cnt ,
3986+ emb0_subsys );
3987+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
3988+ "2449 SLI_CONFIG(mse) rd non-embedded "
3989+ "hbd count = %d\n" ,
3990+ hbd_cnt );
3991+
3992+ ext_dmabuf_list =
3993+ & phba -> mbox_ext_buf_ctx .ext_dmabuf_list ;
3994+
3995+ /* Allocate hbds */
3996+ for (i = 0 ; i < hbd_cnt ; i ++ ) {
3997+ ext_dmabuf = lpfc_bsg_dma_page_alloc (phba );
3998+ if (!ext_dmabuf ) {
3999+ rc = - ENOMEM ;
4000+ goto job_error ;
4001+ }
4002+ list_add_tail (& ext_dmabuf -> list ,
4003+ ext_dmabuf_list );
4004+ }
4005+
4006+ /* Fill out the physical memory addresses for the
4007+ * hbds
4008+ */
4009+ i = 0 ;
4010+ list_for_each_entry_safe (curr_dmabuf , next_dmabuf ,
4011+ ext_dmabuf_list , list ) {
4012+ emb0_subsys -> hbd [i ].pa_hi =
4013+ putPaddrHigh (curr_dmabuf -> phys );
4014+ emb0_subsys -> hbd [i ].pa_lo =
4015+ putPaddrLow (curr_dmabuf -> phys );
4016+
4017+ lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
4018+ "2495 SLI_CONFIG(hbd)[%d], "
4019+ "bufLen:%d, addrHi:x%x, "
4020+ "addrLo:x%x\n" , i ,
4021+ emb0_subsys -> hbd [i ].buf_len ,
4022+ emb0_subsys -> hbd [i ].pa_hi ,
4023+ emb0_subsys -> hbd [i ].pa_lo );
4024+ i ++ ;
4025+ }
4026+ break ;
4027+ default :
4028+ break ;
4029+ }
4030+
38504031 lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
38514032 "2941 Handled SLI_CONFIG(mse) rd, "
38524033 "ext_buf_cnt:%d\n" , ext_buf_cnt );
@@ -4223,6 +4404,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct bsg_job *job,
42234404 case COMN_OPCODE_GET_CNTL_ATTRIBUTES :
42244405 case COMN_OPCODE_GET_PROFILE_CONFIG :
42254406 case COMN_OPCODE_SET_FEATURES :
4407+ case COMN_OPCODE_READ_OBJECT :
42264408 lpfc_printf_log (phba , KERN_INFO , LOG_LIBDFC ,
42274409 "3106 Handled SLI_CONFIG "
42284410 "subsys_comn, opcode:x%x\n" ,
@@ -4665,8 +4847,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct bsg_job *job,
46654847 bsg_reply -> reply_payload_rcv_len = 0 ;
46664848
46674849 /* sanity check to protect driver */
4668- if (job -> reply_payload .payload_len > BSG_MBOX_SIZE ||
4669- job -> request_payload .payload_len > BSG_MBOX_SIZE ) {
4850+ if (job -> request_payload .payload_len > BSG_MBOX_SIZE ) {
46704851 rc = - ERANGE ;
46714852 goto job_done ;
46724853 }
@@ -4737,6 +4918,19 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct bsg_job *job,
47374918 pmb -> mbxOwner = OWN_HOST ;
47384919 pmboxq -> vport = vport ;
47394920
4921+ /* non-embedded SLI_CONFIG requests already parsed, check others */
4922+ if (unlikely (job -> reply_payload .payload_len > BSG_MBOX_SIZE )) {
4923+ lpfc_printf_log (phba , KERN_WARNING , LOG_LIBDFC ,
4924+ "2729 Cmd x%x (x%x/x%x) request has "
4925+ "out-of-range reply payload length x%x\n" ,
4926+ pmb -> mbxCommand ,
4927+ lpfc_sli_config_mbox_subsys_get (phba , pmboxq ),
4928+ lpfc_sli_config_mbox_opcode_get (phba , pmboxq ),
4929+ job -> reply_payload .payload_len );
4930+ rc = - ERANGE ;
4931+ goto job_done ;
4932+ }
4933+
47404934 /* If HBA encountered an error attention, allow only DUMP
47414935 * or RESTART mailbox commands until the HBA is restarted.
47424936 */
0 commit comments