tree: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next head: 1c356ec5e932c8d4c83d9782ab3c4164b6471d5d commit: 016d5c35e27824f31c394009dd0f72f2c6b0dc85 [182/194] scsi: mpt3sas: SGL to PRP Translation for I/Os to NVMe devices config: i386-randconfig-x071-201744 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: git checkout 016d5c35e27824f31c394009dd0f72f2c6b0dc85 # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): drivers/scsi//mpt3sas/mpt3sas_base.c: In function 'base_make_prp_nvme': >> drivers/scsi//mpt3sas/mpt3sas_base.c:1418:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] msg_phys = (dma_addr_t)mpt3sas_base_get_pcie_sgl_dma(ioc, smid); ^ vim +1418 drivers/scsi//mpt3sas/mpt3sas_base.c 1347 1348 /** 1349 * base_make_prp_nvme - 1350 * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only 1351 * 1352 * @ioc: per adapter object 1353 * @scmd: SCSI command from the mid-layer 1354 * @mpi_request: mpi request 1355 * @smid: msg Index 1356 * @sge_count: scatter gather element count. 1357 * 1358 * Returns: true: PRPs are built 1359 * false: IEEE SGLs needs to be built 1360 */ 1361 void 1362 base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc, 1363 struct scsi_cmnd *scmd, 1364 Mpi25SCSIIORequest_t *mpi_request, 1365 u16 smid, int sge_count) 1366 { 1367 int sge_len, offset, num_prp_in_chain = 0; 1368 Mpi25IeeeSgeChain64_t *main_chain_element, *ptr_first_sgl; 1369 u64 *curr_buff; 1370 dma_addr_t msg_phys; 1371 u64 sge_addr; 1372 u32 page_mask, page_mask_result; 1373 struct scatterlist *sg_scmd; 1374 u32 first_prp_len; 1375 int data_len = scsi_bufflen(scmd); 1376 u32 nvme_pg_size; 1377 1378 nvme_pg_size = max_t(u32, ioc->page_size, NVME_PRP_PAGE_SIZE); 1379 /* 1380 * Nvme has a very convoluted prp format. One prp is required 1381 * for each page or partial page. Driver need to split up OS sg_list 1382 * entries if it is longer than one page or cross a page 1383 * boundary. Driver also have to insert a PRP list pointer entry as 1384 * the last entry in each physical page of the PRP list. 1385 * 1386 * NOTE: The first PRP "entry" is actually placed in the first 1387 * SGL entry in the main message as IEEE 64 format. The 2nd 1388 * entry in the main message is the chain element, and the rest 1389 * of the PRP entries are built in the contiguous pcie buffer. 1390 */ 1391 page_mask = nvme_pg_size - 1; 1392 1393 /* 1394 * Native SGL is needed. 1395 * Put a chain element in main message frame that points to the first 1396 * chain buffer. 1397 * 1398 * NOTE: The ChainOffset field must be 0 when using a chain pointer to 1399 * a native SGL. 1400 */ 1401 1402 /* Set main message chain element pointer */ 1403 main_chain_element = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL; 1404 /* 1405 * For NVMe the chain element needs to be the 2nd SG entry in the main 1406 * message. 1407 */ 1408 main_chain_element = (Mpi25IeeeSgeChain64_t *) 1409 ((u8 *)main_chain_element + sizeof(MPI25_IEEE_SGE_CHAIN64)); 1410 1411 /* 1412 * For the PRP entries, use the specially allocated buffer of 1413 * contiguous memory. Normal chain buffers can't be used 1414 * because each chain buffer would need to be the size of an OS 1415 * page (4k). 1416 */ 1417 curr_buff = mpt3sas_base_get_pcie_sgl(ioc, smid); > 1418 msg_phys = (dma_addr_t)mpt3sas_base_get_pcie_sgl_dma(ioc, smid); 1419 1420 main_chain_element->Address = cpu_to_le64(msg_phys); 1421 main_chain_element->NextChainOffset = 0; 1422 main_chain_element->Flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | 1423 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | 1424 MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP; 1425 1426 /* Build first prp, sge need not to be page aligned*/ 1427 ptr_first_sgl = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL; 1428 sg_scmd = scsi_sglist(scmd); 1429 sge_addr = sg_dma_address(sg_scmd); 1430 sge_len = sg_dma_len(sg_scmd); 1431 1432 offset = (u32)(sge_addr & page_mask); 1433 first_prp_len = nvme_pg_size - offset; 1434 1435 ptr_first_sgl->Address = cpu_to_le64(sge_addr); 1436 ptr_first_sgl->Length = cpu_to_le32(first_prp_len); 1437 1438 data_len -= first_prp_len; 1439 1440 if (sge_len > first_prp_len) { 1441 sge_addr += first_prp_len; 1442 sge_len -= first_prp_len; 1443 } else if (data_len && (sge_len == first_prp_len)) { 1444 sg_scmd = sg_next(sg_scmd); 1445 sge_addr = sg_dma_address(sg_scmd); 1446 sge_len = sg_dma_len(sg_scmd); 1447 } 1448 1449 for (;;) { 1450 offset = (u32)(sge_addr & page_mask); 1451 1452 /* Put PRP pointer due to page boundary*/ 1453 page_mask_result = (uintptr_t)(curr_buff + 1) & page_mask; 1454 if (unlikely(!page_mask_result)) { 1455 scmd_printk(KERN_NOTICE, 1456 scmd, "page boundary curr_buff: 0x%p\n", 1457 curr_buff); 1458 msg_phys += 8; 1459 *curr_buff = cpu_to_le64(msg_phys); 1460 curr_buff++; 1461 num_prp_in_chain++; 1462 } 1463 1464 *curr_buff = cpu_to_le64(sge_addr); 1465 curr_buff++; 1466 msg_phys += 8; 1467 num_prp_in_chain++; 1468 1469 sge_addr += nvme_pg_size; 1470 sge_len -= nvme_pg_size; 1471 data_len -= nvme_pg_size; 1472 1473 if (data_len <= 0) 1474 break; 1475 1476 if (sge_len > 0) 1477 continue; 1478 1479 sg_scmd = sg_next(sg_scmd); 1480 sge_addr = sg_dma_address(sg_scmd); 1481 sge_len = sg_dma_len(sg_scmd); 1482 } 1483 1484 main_chain_element->Length = 1485 cpu_to_le32(num_prp_in_chain * sizeof(u64)); 1486 return; 1487 } 1488 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Attachment:
.config.gz
Description: application/gzip