Skip to content

Commit 3103af8

Browse files
Justin Teemartinkpetersen
authored andcommitted
scsi: lpfc: Add support for large fw object application layer reads
Current lpfc bsg implementation allows a maximum fw read object size of 30KB. Implementation and support for read object mailbox commands for fw objects larger than 30KB are now required for proprietary applications. Thus, update the lpfc_sli_config_emb0_subsys structure and its associated submission and completion paths to accommodate for an alternative form of read object command that supports large fw objects. Signed-off-by: Justin Tee <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 91b9130 commit 3103af8

File tree

3 files changed

+224
-9
lines changed

3 files changed

+224
-9
lines changed

drivers/scsi/lpfc/lpfc_bsg.c

Lines changed: 202 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
123133
struct 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
*/

drivers/scsi/lpfc/lpfc_bsg.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,27 @@ struct lpfc_sli_config_emb0_subsys {
239239
uint32_t timeout; /* comn_set_feature timeout */
240240
uint32_t request_length; /* comn_set_feature request len */
241241
uint32_t version; /* comn_set_feature version */
242-
uint32_t csf_feature; /* comn_set_feature feature */
242+
uint32_t word68; /* comn_set_feature feature */
243+
#define lpfc_emb0_subcmnd_csf_feat_SHIFT 0
244+
#define lpfc_emb0_subcmnd_csf_feat_MASK 0xffffffff
245+
#define lpfc_emb0_subcmnd_csf_feat_WORD word68
246+
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_SHIFT 0
247+
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_MASK 0x00ffffff
248+
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_WORD word68
243249
uint32_t word69; /* comn_set_feature parameter len */
244250
uint32_t word70; /* comn_set_feature parameter val0 */
245251
#define lpfc_emb0_subcmnd_csf_p0_SHIFT 0
246252
#define lpfc_emb0_subcmnd_csf_p0_MASK 0x3
247253
#define lpfc_emb0_subcmnd_csf_p0_WORD word70
254+
uint32_t reserved71[25];
255+
uint32_t word96; /* rd_obj hbd_count */
256+
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_SHIFT 0
257+
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_MASK 0xffffffff
258+
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_WORD word96
259+
#define LPFC_EMB0_MAX_RD_OBJ_HBD_CNT 31
260+
struct lpfc_sli_config_hbd hbd[LPFC_EMB0_MAX_RD_OBJ_HBD_CNT];
261+
uint32_t word190;
262+
uint32_t word191;
248263
};
249264

250265
struct lpfc_sli_config_emb1_subsys {

drivers/scsi/lpfc/lpfc_scsi.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5136,6 +5136,12 @@ lpfc_info(struct Scsi_Host *host)
51365136
goto buffer_done;
51375137
}
51385138

5139+
/* Support for BSG ioctls */
5140+
scnprintf(tmp, sizeof(tmp), " BSG");
5141+
if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
5142+
sizeof(lpfcinfobuf))
5143+
goto buffer_done;
5144+
51395145
/* PCI resettable */
51405146
if (!lpfc_check_pci_resettable(phba)) {
51415147
scnprintf(tmp, sizeof(tmp), " PCI resettable");

0 commit comments

Comments
 (0)