diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 163 |
1 files changed, 119 insertions, 44 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index a22bdf9548a6..c1bb90cf0d06 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -198,7 +198,9 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) | |||
198 | struct lpfc_scsi_buf *psb; | 198 | struct lpfc_scsi_buf *psb; |
199 | struct ulp_bde64 *bpl; | 199 | struct ulp_bde64 *bpl; |
200 | IOCB_t *iocb; | 200 | IOCB_t *iocb; |
201 | dma_addr_t pdma_phys; | 201 | dma_addr_t pdma_phys_fcp_cmd; |
202 | dma_addr_t pdma_phys_fcp_rsp; | ||
203 | dma_addr_t pdma_phys_bpl; | ||
202 | uint16_t iotag; | 204 | uint16_t iotag; |
203 | 205 | ||
204 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); | 206 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); |
@@ -238,40 +240,60 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) | |||
238 | 240 | ||
239 | /* Initialize local short-hand pointers. */ | 241 | /* Initialize local short-hand pointers. */ |
240 | bpl = psb->fcp_bpl; | 242 | bpl = psb->fcp_bpl; |
241 | pdma_phys = psb->dma_handle; | 243 | pdma_phys_fcp_cmd = psb->dma_handle; |
244 | pdma_phys_fcp_rsp = psb->dma_handle + sizeof(struct fcp_cmnd); | ||
245 | pdma_phys_bpl = psb->dma_handle + sizeof(struct fcp_cmnd) + | ||
246 | sizeof(struct fcp_rsp); | ||
242 | 247 | ||
243 | /* | 248 | /* |
244 | * The first two bdes are the FCP_CMD and FCP_RSP. The balance are sg | 249 | * The first two bdes are the FCP_CMD and FCP_RSP. The balance are sg |
245 | * list bdes. Initialize the first two and leave the rest for | 250 | * list bdes. Initialize the first two and leave the rest for |
246 | * queuecommand. | 251 | * queuecommand. |
247 | */ | 252 | */ |
248 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys)); | 253 | bpl[0].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_cmd)); |
249 | bpl->addrLow = le32_to_cpu(putPaddrLow(pdma_phys)); | 254 | bpl[0].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_cmd)); |
250 | bpl->tus.f.bdeSize = sizeof (struct fcp_cmnd); | 255 | bpl[0].tus.f.bdeSize = sizeof(struct fcp_cmnd); |
251 | bpl->tus.f.bdeFlags = BUFF_USE_CMND; | 256 | bpl[0].tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
252 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 257 | bpl[0].tus.w = le32_to_cpu(bpl->tus.w); |
253 | bpl++; | ||
254 | 258 | ||
255 | /* Setup the physical region for the FCP RSP */ | 259 | /* Setup the physical region for the FCP RSP */ |
256 | pdma_phys += sizeof (struct fcp_cmnd); | 260 | bpl[1].addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys_fcp_rsp)); |
257 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(pdma_phys)); | 261 | bpl[1].addrLow = le32_to_cpu(putPaddrLow(pdma_phys_fcp_rsp)); |
258 | bpl->addrLow = le32_to_cpu(putPaddrLow(pdma_phys)); | 262 | bpl[1].tus.f.bdeSize = sizeof(struct fcp_rsp); |
259 | bpl->tus.f.bdeSize = sizeof (struct fcp_rsp); | 263 | bpl[1].tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
260 | bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV); | 264 | bpl[1].tus.w = le32_to_cpu(bpl->tus.w); |
261 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
262 | 265 | ||
263 | /* | 266 | /* |
264 | * Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf, | 267 | * Since the IOCB for the FCP I/O is built into this lpfc_scsi_buf, |
265 | * initialize it with all known data now. | 268 | * initialize it with all known data now. |
266 | */ | 269 | */ |
267 | pdma_phys += (sizeof (struct fcp_rsp)); | ||
268 | iocb = &psb->cur_iocbq.iocb; | 270 | iocb = &psb->cur_iocbq.iocb; |
269 | iocb->un.fcpi64.bdl.ulpIoTag32 = 0; | 271 | iocb->un.fcpi64.bdl.ulpIoTag32 = 0; |
270 | iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys); | 272 | if (phba->sli_rev == 3) { |
271 | iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys); | 273 | /* fill in immediate fcp command BDE */ |
272 | iocb->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); | 274 | iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_IMMED; |
273 | iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDL; | 275 | iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd); |
274 | iocb->ulpBdeCount = 1; | 276 | iocb->un.fcpi64.bdl.addrLow = offsetof(IOCB_t, |
277 | unsli3.fcp_ext.icd); | ||
278 | iocb->un.fcpi64.bdl.addrHigh = 0; | ||
279 | iocb->ulpBdeCount = 0; | ||
280 | iocb->ulpLe = 0; | ||
281 | /* fill in responce BDE */ | ||
282 | iocb->unsli3.fcp_ext.rbde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
283 | iocb->unsli3.fcp_ext.rbde.tus.f.bdeSize = | ||
284 | sizeof(struct fcp_rsp); | ||
285 | iocb->unsli3.fcp_ext.rbde.addrLow = | ||
286 | putPaddrLow(pdma_phys_fcp_rsp); | ||
287 | iocb->unsli3.fcp_ext.rbde.addrHigh = | ||
288 | putPaddrHigh(pdma_phys_fcp_rsp); | ||
289 | } else { | ||
290 | iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BLP_64; | ||
291 | iocb->un.fcpi64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); | ||
292 | iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys_bpl); | ||
293 | iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys_bpl); | ||
294 | iocb->ulpBdeCount = 1; | ||
295 | iocb->ulpLe = 1; | ||
296 | } | ||
275 | iocb->ulpClass = CLASS3; | 297 | iocb->ulpClass = CLASS3; |
276 | 298 | ||
277 | return psb; | 299 | return psb; |
@@ -313,8 +335,9 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
313 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; | 335 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; |
314 | struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; | 336 | struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; |
315 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; | 337 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; |
338 | struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde; | ||
316 | dma_addr_t physaddr; | 339 | dma_addr_t physaddr; |
317 | uint32_t i, num_bde = 0; | 340 | uint32_t num_bde = 0; |
318 | int nseg, datadir = scsi_cmnd->sc_data_direction; | 341 | int nseg, datadir = scsi_cmnd->sc_data_direction; |
319 | 342 | ||
320 | /* | 343 | /* |
@@ -352,33 +375,64 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
352 | * during probe that limits the number of sg elements in any | 375 | * during probe that limits the number of sg elements in any |
353 | * single scsi command. Just run through the seg_cnt and format | 376 | * single scsi command. Just run through the seg_cnt and format |
354 | * the bde's. | 377 | * the bde's. |
378 | * When using SLI-3 the driver will try to fit all the BDEs into | ||
379 | * the IOCB. If it can't then the BDEs get added to a BPL as it | ||
380 | * does for SLI-2 mode. | ||
355 | */ | 381 | */ |
356 | scsi_for_each_sg(scsi_cmnd, sgel, nseg, i) { | 382 | scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) { |
357 | physaddr = sg_dma_address(sgel); | 383 | physaddr = sg_dma_address(sgel); |
358 | bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr)); | 384 | if (phba->sli_rev == 3 && |
359 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); | 385 | nseg <= LPFC_EXT_DATA_BDE_COUNT) { |
360 | bpl->tus.f.bdeSize = sg_dma_len(sgel); | 386 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
361 | if (datadir == DMA_TO_DEVICE) | 387 | data_bde->tus.f.bdeSize = sg_dma_len(sgel); |
362 | bpl->tus.f.bdeFlags = 0; | 388 | data_bde->addrLow = putPaddrLow(physaddr); |
363 | else | 389 | data_bde->addrHigh = putPaddrHigh(physaddr); |
364 | bpl->tus.f.bdeFlags = BUFF_USE_RCV; | 390 | data_bde++; |
365 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 391 | } else { |
366 | bpl++; | 392 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
367 | num_bde++; | 393 | bpl->tus.f.bdeSize = sg_dma_len(sgel); |
394 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
395 | bpl->addrLow = | ||
396 | le32_to_cpu(putPaddrLow(physaddr)); | ||
397 | bpl->addrHigh = | ||
398 | le32_to_cpu(putPaddrHigh(physaddr)); | ||
399 | bpl++; | ||
400 | } | ||
368 | } | 401 | } |
369 | } | 402 | } |
370 | 403 | ||
371 | /* | 404 | /* |
372 | * Finish initializing those IOCB fields that are dependent on the | 405 | * Finish initializing those IOCB fields that are dependent on the |
373 | * scsi_cmnd request_buffer. Note that the bdeSize is explicitly | 406 | * scsi_cmnd request_buffer. Note that for SLI-2 the bdeSize is |
374 | * reinitialized since all iocb memory resources are used many times | 407 | * explicitly reinitialized and for SLI-3 the extended bde count is |
375 | * for transmit, receive, and continuation bpl's. | 408 | * explicitly reinitialized since all iocb memory resources are reused. |
376 | */ | 409 | */ |
377 | iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); | 410 | if (phba->sli_rev == 3) { |
378 | iocb_cmd->un.fcpi64.bdl.bdeSize += | 411 | if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { |
379 | (num_bde * sizeof (struct ulp_bde64)); | 412 | /* |
380 | iocb_cmd->ulpBdeCount = 1; | 413 | * The extended IOCB format can only fit 3 BDE or a BPL. |
381 | iocb_cmd->ulpLe = 1; | 414 | * This I/O has more than 3 BDE so the 1st data bde will |
415 | * be a BPL that is filled in here. | ||
416 | */ | ||
417 | physaddr = lpfc_cmd->dma_handle; | ||
418 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BLP_64; | ||
419 | data_bde->tus.f.bdeSize = (num_bde * | ||
420 | sizeof(struct ulp_bde64)); | ||
421 | physaddr += (sizeof(struct fcp_cmnd) + | ||
422 | sizeof(struct fcp_rsp) + | ||
423 | (2 * sizeof(struct ulp_bde64))); | ||
424 | data_bde->addrHigh = putPaddrHigh(physaddr); | ||
425 | data_bde->addrLow = putPaddrLow(physaddr); | ||
426 | /* ebde count includes the responce bde and data bpl */ | ||
427 | iocb_cmd->unsli3.fcp_ext.ebde_count = 2; | ||
428 | } else { | ||
429 | /* ebde count includes the responce bde and data bdes */ | ||
430 | iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1); | ||
431 | } | ||
432 | } else { | ||
433 | iocb_cmd->un.fcpi64.bdl.bdeSize = | ||
434 | ((num_bde + 2) * sizeof(struct ulp_bde64)); | ||
435 | } | ||
382 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); | 436 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); |
383 | return 0; | 437 | return 0; |
384 | } | 438 | } |
@@ -692,6 +746,24 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
692 | lpfc_release_scsi_buf(phba, lpfc_cmd); | 746 | lpfc_release_scsi_buf(phba, lpfc_cmd); |
693 | } | 747 | } |
694 | 748 | ||
749 | /** | ||
750 | * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB. | ||
751 | * @data: A pointer to the immediate command data portion of the IOCB. | ||
752 | * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. | ||
753 | * | ||
754 | * The routine copies the entire FCP command from @fcp_cmnd to @data while | ||
755 | * byte swapping the data to big endian format for transmission on the wire. | ||
756 | **/ | ||
757 | static void | ||
758 | lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd) | ||
759 | { | ||
760 | int i, j; | ||
761 | for (i = 0, j = 0; i < sizeof(struct fcp_cmnd); | ||
762 | i += sizeof(uint32_t), j++) { | ||
763 | ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]); | ||
764 | } | ||
765 | } | ||
766 | |||
695 | static void | 767 | static void |
696 | lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | 768 | lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, |
697 | struct lpfc_nodelist *pnode) | 769 | struct lpfc_nodelist *pnode) |
@@ -758,7 +830,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
758 | fcp_cmnd->fcpCntl3 = 0; | 830 | fcp_cmnd->fcpCntl3 = 0; |
759 | phba->fc4ControlRequests++; | 831 | phba->fc4ControlRequests++; |
760 | } | 832 | } |
761 | 833 | if (phba->sli_rev == 3) | |
834 | lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); | ||
762 | /* | 835 | /* |
763 | * Finish initializing those IOCB fields that are independent | 836 | * Finish initializing those IOCB fields that are independent |
764 | * of the scsi_cmnd request_buffer | 837 | * of the scsi_cmnd request_buffer |
@@ -798,11 +871,13 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, | |||
798 | piocb = &piocbq->iocb; | 871 | piocb = &piocbq->iocb; |
799 | 872 | ||
800 | fcp_cmnd = lpfc_cmd->fcp_cmnd; | 873 | fcp_cmnd = lpfc_cmd->fcp_cmnd; |
801 | int_to_scsilun(lun, &lpfc_cmd->fcp_cmnd->fcp_lun); | 874 | /* Clear out any old data in the FCP command area */ |
875 | memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); | ||
876 | int_to_scsilun(lun, &fcp_cmnd->fcp_lun); | ||
802 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; | 877 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; |
803 | 878 | if (vport->phba->sli_rev == 3) | |
879 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); | ||
804 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; | 880 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; |
805 | |||
806 | piocb->ulpContext = ndlp->nlp_rpi; | 881 | piocb->ulpContext = ndlp->nlp_rpi; |
807 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { | 882 | if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
808 | piocb->ulpFCP2Rcvy = 1; | 883 | piocb->ulpFCP2Rcvy = 1; |