Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/ehca: Restructure ehca_set_pagebuf()

Split ehca_set_pagebuf() into three functions depending on MR type
(phys/user/fast) and remove superfluous ehca_set_pagebuf_1().

Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Hoang-Nam Nguyen and committed by
Roland Dreier
187c72e3 df17bfd4

+209 -340
+209 -340
drivers/infiniband/hw/ehca/ehca_mrmw.c
··· 824 824 pginfo.u.fmr.page_list = page_list; 825 825 pginfo.next_hwpage = ((iova & (e_fmr->fmr_page_size-1)) / 826 826 EHCA_PAGESIZE); 827 + pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size; 827 828 828 829 ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova, 829 830 list_len * e_fmr->fmr_page_size, ··· 1045 1044 } else 1046 1045 rnum = MAX_RPAGES; 1047 1046 1048 - if (rnum > 1) { 1049 - ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage); 1050 - if (ret) { 1051 - ehca_err(&shca->ib_device, "ehca_set_pagebuf " 1047 + ret = ehca_set_pagebuf(pginfo, rnum, kpage); 1048 + if (ret) { 1049 + ehca_err(&shca->ib_device, "ehca_set_pagebuf " 1052 1050 "bad rc, ret=%x rnum=%x kpage=%p", 1053 1051 ret, rnum, kpage); 1054 - ret = -EFAULT; 1055 - goto ehca_reg_mr_rpages_exit1; 1056 - } 1052 + goto ehca_reg_mr_rpages_exit1; 1053 + } 1054 + 1055 + if (rnum > 1) { 1057 1056 rpage = virt_to_abs(kpage); 1058 1057 if (!rpage) { 1059 1058 ehca_err(&shca->ib_device, "kpage=%p i=%x", ··· 1061 1060 ret = -EFAULT; 1062 1061 goto ehca_reg_mr_rpages_exit1; 1063 1062 } 1064 - } else { /* rnum==1 */ 1065 - ret = ehca_set_pagebuf_1(e_mr, pginfo, &rpage); 1066 - if (ret) { 1067 - ehca_err(&shca->ib_device, "ehca_set_pagebuf_1 " 1068 - "bad rc, ret=%x i=%x", ret, i); 1069 - ret = -EFAULT; 1070 - goto ehca_reg_mr_rpages_exit1; 1071 - } 1072 - } 1063 + } else 1064 + rpage = *kpage; 1073 1065 1074 1066 h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr, 1075 1067 0, /* pagesize 4k */ ··· 1140 1146 } 1141 1147 1142 1148 pginfo_save = *pginfo; 1143 - ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_hwpages, kpage); 1149 + ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage); 1144 1150 if (ret) { 1145 1151 ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p " 1146 1152 "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx " ··· 1300 1306 { 1301 1307 int ret = 0; 1302 1308 u64 h_ret; 1303 - int rereg_1_hcall = 1; /* 1: use hipz_mr_reregister directly */ 1304 - int rereg_3_hcall = 0; /* 1: use 3 hipz calls for unmapping */ 1305 1309 struct ehca_pd *e_pd = 1306 1310 container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd); 1307 1311 struct ehca_mr save_fmr; 1308 1312 u32 tmp_lkey, tmp_rkey; 1309 1313 struct ehca_mr_pginfo pginfo; 1310 1314 struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 1315 + struct ehca_mr save_mr; 1311 1316 1312 - /* first check if reregistration hCall can be used for unmap */ 1313 - if (e_fmr->fmr_max_pages > MAX_RPAGES) { 1314 - rereg_1_hcall = 0; 1315 - rereg_3_hcall = 1; 1316 - } 1317 - 1318 - if (rereg_1_hcall) { 1317 + if (e_fmr->fmr_max_pages <= MAX_RPAGES) { 1319 1318 /* 1320 1319 * note: after using rereg hcall with len=0, 1321 1320 * rereg hcall must be used again for registering pages 1322 1321 */ 1323 1322 h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0, 1324 1323 0, 0, e_pd->fw_pd, 0, &hipzout); 1325 - if (h_ret != H_SUCCESS) { 1326 - /* 1327 - * should not happen, because length checked above, 1328 - * FMRs are not shared and no MW bound to FMRs 1329 - */ 1330 - ehca_err(&shca->ib_device, "hipz_reregister_pmr failed " 1331 - "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx " 1332 - "mr_hndl=%lx lkey=%x lkey_out=%x", 1333 - h_ret, e_fmr, shca->ipz_hca_handle.handle, 1334 - e_fmr->ipz_mr_handle.handle, 1335 - e_fmr->ib.ib_fmr.lkey, hipzout.lkey); 1336 - rereg_3_hcall = 1; 1337 - } else { 1324 + if (h_ret == H_SUCCESS) { 1338 1325 /* successful reregistration */ 1339 1326 e_fmr->start = NULL; 1340 1327 e_fmr->size = 0; 1341 1328 tmp_lkey = hipzout.lkey; 1342 1329 tmp_rkey = hipzout.rkey; 1330 + return 0; 1343 1331 } 1332 + /* 1333 + * should not happen, because length checked above, 1334 + * FMRs are not shared and no MW bound to FMRs 1335 + */ 1336 + ehca_err(&shca->ib_device, "hipz_reregister_pmr failed " 1337 + "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx " 1338 + "mr_hndl=%lx lkey=%x lkey_out=%x", 1339 + h_ret, e_fmr, shca->ipz_hca_handle.handle, 1340 + e_fmr->ipz_mr_handle.handle, 1341 + e_fmr->ib.ib_fmr.lkey, hipzout.lkey); 1342 + /* try free and rereg */ 1344 1343 } 1345 1344 1346 - if (rereg_3_hcall) { 1347 - struct ehca_mr save_mr; 1345 + /* first free old FMR */ 1346 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); 1347 + if (h_ret != H_SUCCESS) { 1348 + ehca_err(&shca->ib_device, "hipz_free_mr failed, " 1349 + "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx " 1350 + "lkey=%x", 1351 + h_ret, e_fmr, shca->ipz_hca_handle.handle, 1352 + e_fmr->ipz_mr_handle.handle, 1353 + e_fmr->ib.ib_fmr.lkey); 1354 + ret = ehca2ib_return_code(h_ret); 1355 + goto ehca_unmap_one_fmr_exit0; 1356 + } 1357 + /* clean ehca_mr_t, without changing lock */ 1358 + save_fmr = *e_fmr; 1359 + ehca_mr_deletenew(e_fmr); 1348 1360 1349 - /* first free old FMR */ 1350 - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); 1351 - if (h_ret != H_SUCCESS) { 1352 - ehca_err(&shca->ib_device, "hipz_free_mr failed, " 1353 - "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx " 1354 - "lkey=%x", 1355 - h_ret, e_fmr, shca->ipz_hca_handle.handle, 1356 - e_fmr->ipz_mr_handle.handle, 1357 - e_fmr->ib.ib_fmr.lkey); 1358 - ret = ehca2ib_return_code(h_ret); 1359 - goto ehca_unmap_one_fmr_exit0; 1360 - } 1361 - /* clean ehca_mr_t, without changing lock */ 1362 - save_fmr = *e_fmr; 1363 - ehca_mr_deletenew(e_fmr); 1361 + /* set some MR values */ 1362 + e_fmr->flags = save_fmr.flags; 1363 + e_fmr->fmr_page_size = save_fmr.fmr_page_size; 1364 + e_fmr->fmr_max_pages = save_fmr.fmr_max_pages; 1365 + e_fmr->fmr_max_maps = save_fmr.fmr_max_maps; 1366 + e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt; 1367 + e_fmr->acl = save_fmr.acl; 1364 1368 1365 - /* set some MR values */ 1366 - e_fmr->flags = save_fmr.flags; 1367 - e_fmr->fmr_page_size = save_fmr.fmr_page_size; 1368 - e_fmr->fmr_max_pages = save_fmr.fmr_max_pages; 1369 - e_fmr->fmr_max_maps = save_fmr.fmr_max_maps; 1370 - e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt; 1371 - e_fmr->acl = save_fmr.acl; 1372 - 1373 - memset(&pginfo, 0, sizeof(pginfo)); 1374 - pginfo.type = EHCA_MR_PGI_FMR; 1375 - pginfo.num_kpages = 0; 1376 - pginfo.num_hwpages = 0; 1377 - ret = ehca_reg_mr(shca, e_fmr, NULL, 1378 - (e_fmr->fmr_max_pages * e_fmr->fmr_page_size), 1379 - e_fmr->acl, e_pd, &pginfo, &tmp_lkey, 1380 - &tmp_rkey); 1381 - if (ret) { 1382 - u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr; 1383 - memcpy(&e_fmr->flags, &(save_mr.flags), 1384 - sizeof(struct ehca_mr) - offset); 1385 - goto ehca_unmap_one_fmr_exit0; 1386 - } 1369 + memset(&pginfo, 0, sizeof(pginfo)); 1370 + pginfo.type = EHCA_MR_PGI_FMR; 1371 + pginfo.num_kpages = 0; 1372 + pginfo.num_hwpages = 0; 1373 + ret = ehca_reg_mr(shca, e_fmr, NULL, 1374 + (e_fmr->fmr_max_pages * e_fmr->fmr_page_size), 1375 + e_fmr->acl, e_pd, &pginfo, &tmp_lkey, 1376 + &tmp_rkey); 1377 + if (ret) { 1378 + u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr; 1379 + memcpy(&e_fmr->flags, &(save_mr.flags), 1380 + sizeof(struct ehca_mr) - offset); 1381 + goto ehca_unmap_one_fmr_exit0; 1387 1382 } 1388 1383 1389 1384 ehca_unmap_one_fmr_exit0: 1390 1385 if (ret) 1391 1386 ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x " 1392 - "fmr_max_pages=%x rereg_1_hcall=%x rereg_3_hcall=%x", 1393 - ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages, 1394 - rereg_1_hcall, rereg_3_hcall); 1387 + "fmr_max_pages=%x", 1388 + ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages); 1395 1389 return ret; 1396 1390 } /* end ehca_unmap_one_fmr() */ 1397 1391 ··· 1672 1690 1673 1691 /*----------------------------------------------------------------------*/ 1674 1692 1675 - /* setup page buffer from page info */ 1676 - int ehca_set_pagebuf(struct ehca_mr *e_mr, 1677 - struct ehca_mr_pginfo *pginfo, 1678 - u32 number, 1679 - u64 *kpage) 1693 + /* PAGE_SIZE >= pginfo->hwpage_size */ 1694 + static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo, 1695 + u32 number, 1696 + u64 *kpage) 1680 1697 { 1681 1698 int ret = 0; 1682 1699 struct ib_umem_chunk *prev_chunk; 1683 1700 struct ib_umem_chunk *chunk; 1684 - struct ib_phys_buf *pbuf; 1685 - u64 *fmrlist; 1686 - u64 num_hw, pgaddr, offs_hw; 1701 + u64 pgaddr; 1687 1702 u32 i = 0; 1688 1703 u32 j = 0; 1689 1704 1690 - if (pginfo->type == EHCA_MR_PGI_PHYS) { 1691 - /* loop over desired phys_buf_array entries */ 1692 - while (i < number) { 1693 - pbuf = pginfo->u.phy.phys_buf_array 1694 - + pginfo->u.phy.next_buf; 1695 - num_hw = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) + 1696 - pbuf->size, EHCA_PAGESIZE); 1697 - offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; 1698 - while (pginfo->next_hwpage < offs_hw + num_hw) { 1699 - /* sanity check */ 1700 - if ((pginfo->kpage_cnt >= pginfo->num_kpages) || 1701 - (pginfo->hwpage_cnt >= pginfo->num_hwpages)) { 1702 - ehca_gen_err("kpage_cnt >= num_kpages, " 1703 - "kpage_cnt=%lx " 1704 - "num_kpages=%lx " 1705 - "hwpage_cnt=%lx " 1706 - "num_hwpages=%lx i=%x", 1707 - pginfo->kpage_cnt, 1708 - pginfo->num_kpages, 1709 - pginfo->hwpage_cnt, 1710 - pginfo->num_hwpages, i); 1711 - ret = -EFAULT; 1712 - goto ehca_set_pagebuf_exit0; 1713 - } 1714 - *kpage = phys_to_abs( 1715 - (pbuf->addr & EHCA_PAGEMASK) 1716 - + (pginfo->next_hwpage * EHCA_PAGESIZE)); 1717 - if ( !(*kpage) && pbuf->addr ) { 1718 - ehca_gen_err("pbuf->addr=%lx " 1719 - "pbuf->size=%lx " 1720 - "next_hwpage=%lx", pbuf->addr, 1721 - pbuf->size, 1722 - pginfo->next_hwpage); 1723 - ret = -EFAULT; 1724 - goto ehca_set_pagebuf_exit0; 1725 - } 1726 - (pginfo->hwpage_cnt)++; 1727 - (pginfo->next_hwpage)++; 1728 - if (pginfo->next_hwpage % 1729 - (PAGE_SIZE / EHCA_PAGESIZE) == 0) 1730 - (pginfo->kpage_cnt)++; 1731 - kpage++; 1732 - i++; 1733 - if (i >= number) break; 1734 - } 1735 - if (pginfo->next_hwpage >= offs_hw + num_hw) { 1736 - (pginfo->u.phy.next_buf)++; 1737 - pginfo->next_hwpage = 0; 1738 - } 1739 - } 1740 - } else if (pginfo->type == EHCA_MR_PGI_USER) { 1741 - /* loop over desired chunk entries */ 1742 - chunk = pginfo->u.usr.next_chunk; 1743 - prev_chunk = pginfo->u.usr.next_chunk; 1744 - list_for_each_entry_continue(chunk, 1745 - (&(pginfo->u.usr.region->chunk_list)), 1746 - list) { 1747 - for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) { 1748 - pgaddr = ( page_to_pfn(chunk->page_list[i].page) 1749 - << PAGE_SHIFT ); 1750 - *kpage = phys_to_abs(pgaddr + 1751 - (pginfo->next_hwpage * 1752 - EHCA_PAGESIZE)); 1753 - if ( !(*kpage) ) { 1754 - ehca_gen_err("pgaddr=%lx " 1755 - "chunk->page_list[i]=%lx " 1756 - "i=%x next_hwpage=%lx mr=%p", 1757 - pgaddr, 1758 - (u64)sg_dma_address( 1759 - &chunk-> 1760 - page_list[i]), 1761 - i, pginfo->next_hwpage, e_mr); 1762 - ret = -EFAULT; 1763 - goto ehca_set_pagebuf_exit0; 1764 - } 1765 - (pginfo->hwpage_cnt)++; 1766 - (pginfo->next_hwpage)++; 1767 - kpage++; 1768 - if (pginfo->next_hwpage % 1769 - (PAGE_SIZE / EHCA_PAGESIZE) == 0) { 1770 - (pginfo->kpage_cnt)++; 1771 - (pginfo->u.usr.next_nmap)++; 1772 - pginfo->next_hwpage = 0; 1773 - i++; 1774 - } 1775 - j++; 1776 - if (j >= number) break; 1777 - } 1778 - if ((pginfo->u.usr.next_nmap >= chunk->nmap) && 1779 - (j >= number)) { 1780 - pginfo->u.usr.next_nmap = 0; 1781 - prev_chunk = chunk; 1782 - break; 1783 - } else if (pginfo->u.usr.next_nmap >= chunk->nmap) { 1784 - pginfo->u.usr.next_nmap = 0; 1785 - prev_chunk = chunk; 1786 - } else if (j >= number) 1787 - break; 1788 - else 1789 - prev_chunk = chunk; 1790 - } 1791 - pginfo->u.usr.next_chunk = 1792 - list_prepare_entry(prev_chunk, 1793 - (&(pginfo->u.usr.region->chunk_list)), 1794 - list); 1795 - } else if (pginfo->type == EHCA_MR_PGI_FMR) { 1796 - /* loop over desired page_list entries */ 1797 - fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem; 1798 - for (i = 0; i < number; i++) { 1799 - *kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + 1800 - pginfo->next_hwpage * EHCA_PAGESIZE); 1705 + /* loop over desired chunk entries */ 1706 + chunk = pginfo->u.usr.next_chunk; 1707 + prev_chunk = pginfo->u.usr.next_chunk; 1708 + list_for_each_entry_continue( 1709 + chunk, (&(pginfo->u.usr.region->chunk_list)), list) { 1710 + for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) { 1711 + pgaddr = page_to_pfn(chunk->page_list[i].page) 1712 + << PAGE_SHIFT ; 1713 + *kpage = phys_to_abs(pgaddr + 1714 + (pginfo->next_hwpage * 1715 + EHCA_PAGESIZE)); 1801 1716 if ( !(*kpage) ) { 1802 - ehca_gen_err("*fmrlist=%lx fmrlist=%p " 1803 - "next_listelem=%lx next_hwpage=%lx", 1804 - *fmrlist, fmrlist, 1805 - pginfo->u.fmr.next_listelem, 1806 - pginfo->next_hwpage); 1807 - ret = -EFAULT; 1808 - goto ehca_set_pagebuf_exit0; 1717 + ehca_gen_err("pgaddr=%lx " 1718 + "chunk->page_list[i]=%lx " 1719 + "i=%x next_hwpage=%lx", 1720 + pgaddr, (u64)sg_dma_address( 1721 + &chunk->page_list[i]), 1722 + i, pginfo->next_hwpage); 1723 + return -EFAULT; 1809 1724 } 1810 1725 (pginfo->hwpage_cnt)++; 1811 1726 (pginfo->next_hwpage)++; 1812 1727 kpage++; 1813 1728 if (pginfo->next_hwpage % 1814 - (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { 1815 - (pginfo->kpage_cnt)++; 1816 - (pginfo->u.fmr.next_listelem)++; 1817 - fmrlist++; 1818 - pginfo->next_hwpage = 0; 1819 - } 1820 - } 1821 - } else { 1822 - ehca_gen_err("bad pginfo->type=%x", pginfo->type); 1823 - ret = -EFAULT; 1824 - goto ehca_set_pagebuf_exit0; 1825 - } 1826 - 1827 - ehca_set_pagebuf_exit0: 1828 - if (ret) 1829 - ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx " 1830 - "num_hwpages=%lx next_buf=%lx next_hwpage=%lx number=%x " 1831 - "kpage=%p kpage_cnt=%lx hwpage_cnt=%lx i=%x " 1832 - "next_listelem=%lx region=%p next_chunk=%p " 1833 - "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type, 1834 - pginfo->num_kpages, pginfo->num_hwpages, 1835 - pginfo->u.phy.next_buf, pginfo->next_hwpage, number, kpage, 1836 - pginfo->kpage_cnt, pginfo->hwpage_cnt, i, 1837 - pginfo->u.fmr.next_listelem, pginfo->u.usr.region, 1838 - pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap); 1839 - return ret; 1840 - } /* end ehca_set_pagebuf() */ 1841 - 1842 - /*----------------------------------------------------------------------*/ 1843 - 1844 - /* setup 1 page from page info page buffer */ 1845 - int ehca_set_pagebuf_1(struct ehca_mr *e_mr, 1846 - struct ehca_mr_pginfo *pginfo, 1847 - u64 *rpage) 1848 - { 1849 - int ret = 0; 1850 - struct ib_phys_buf *tmp_pbuf; 1851 - u64 *fmrlist; 1852 - struct ib_umem_chunk *chunk; 1853 - struct ib_umem_chunk *prev_chunk; 1854 - u64 pgaddr, num_hw, offs_hw; 1855 - 1856 - if (pginfo->type == EHCA_MR_PGI_PHYS) { 1857 - /* sanity check */ 1858 - if ((pginfo->kpage_cnt >= pginfo->num_kpages) || 1859 - (pginfo->hwpage_cnt >= pginfo->num_hwpages)) { 1860 - ehca_gen_err("kpage_cnt >= num_hwpages, kpage_cnt=%lx " 1861 - "num_hwpages=%lx hwpage_cnt=%lx num_hwpages=%lx", 1862 - pginfo->kpage_cnt, pginfo->num_kpages, 1863 - pginfo->hwpage_cnt, pginfo->num_hwpages); 1864 - ret = -EFAULT; 1865 - goto ehca_set_pagebuf_1_exit0; 1866 - } 1867 - tmp_pbuf = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf; 1868 - num_hw = NUM_CHUNKS((tmp_pbuf->addr % EHCA_PAGESIZE) + 1869 - tmp_pbuf->size, EHCA_PAGESIZE); 1870 - offs_hw = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; 1871 - *rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) + 1872 - (pginfo->next_hwpage * EHCA_PAGESIZE)); 1873 - if ( !(*rpage) && tmp_pbuf->addr ) { 1874 - ehca_gen_err("tmp_pbuf->addr=%lx" 1875 - " tmp_pbuf->size=%lx next_hwpage=%lx", 1876 - tmp_pbuf->addr, tmp_pbuf->size, 1877 - pginfo->next_hwpage); 1878 - ret = -EFAULT; 1879 - goto ehca_set_pagebuf_1_exit0; 1880 - } 1881 - (pginfo->hwpage_cnt)++; 1882 - (pginfo->next_hwpage)++; 1883 - if (pginfo->next_hwpage % (PAGE_SIZE / EHCA_PAGESIZE) == 0) 1884 - (pginfo->kpage_cnt)++; 1885 - if (pginfo->next_hwpage >= offs_hw + num_hw) { 1886 - (pginfo->u.phy.next_buf)++; 1887 - pginfo->next_hwpage = 0; 1888 - } 1889 - } else if (pginfo->type == EHCA_MR_PGI_USER) { 1890 - chunk = pginfo->u.usr.next_chunk; 1891 - prev_chunk = pginfo->u.usr.next_chunk; 1892 - list_for_each_entry_continue(chunk, 1893 - (&(pginfo->u.usr.region->chunk_list)), 1894 - list) { 1895 - pgaddr = ( page_to_pfn(chunk->page_list[ 1896 - pginfo->u.usr.next_nmap].page) 1897 - << PAGE_SHIFT); 1898 - *rpage = phys_to_abs(pgaddr + 1899 - (pginfo->next_hwpage * EHCA_PAGESIZE)); 1900 - if ( !(*rpage) ) { 1901 - ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx" 1902 - " next_nmap=%lx next_hwpage=%lx mr=%p", 1903 - pgaddr, (u64)sg_dma_address( 1904 - &chunk->page_list[ 1905 - pginfo->u.usr. 1906 - next_nmap]), 1907 - pginfo->u.usr.next_nmap, pginfo->next_hwpage, 1908 - e_mr); 1909 - ret = -EFAULT; 1910 - goto ehca_set_pagebuf_1_exit0; 1911 - } 1912 - (pginfo->hwpage_cnt)++; 1913 - (pginfo->next_hwpage)++; 1914 - if (pginfo->next_hwpage % 1915 1729 (PAGE_SIZE / EHCA_PAGESIZE) == 0) { 1916 1730 (pginfo->kpage_cnt)++; 1917 1731 (pginfo->u.usr.next_nmap)++; 1918 1732 pginfo->next_hwpage = 0; 1733 + i++; 1919 1734 } 1920 - if (pginfo->u.usr.next_nmap >= chunk->nmap) { 1921 - pginfo->u.usr.next_nmap = 0; 1922 - prev_chunk = chunk; 1923 - } 1924 - break; 1735 + j++; 1736 + if (j >= number) break; 1925 1737 } 1926 - pginfo->u.usr.next_chunk = 1927 - list_prepare_entry(prev_chunk, 1928 - (&(pginfo->u.usr.region->chunk_list)), 1929 - list); 1930 - } else if (pginfo->type == EHCA_MR_PGI_FMR) { 1931 - fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem; 1932 - *rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + 1738 + if ((pginfo->u.usr.next_nmap >= chunk->nmap) && 1739 + (j >= number)) { 1740 + pginfo->u.usr.next_nmap = 0; 1741 + prev_chunk = chunk; 1742 + break; 1743 + } else if (pginfo->u.usr.next_nmap >= chunk->nmap) { 1744 + pginfo->u.usr.next_nmap = 0; 1745 + prev_chunk = chunk; 1746 + } else if (j >= number) 1747 + break; 1748 + else 1749 + prev_chunk = chunk; 1750 + } 1751 + pginfo->u.usr.next_chunk = 1752 + list_prepare_entry(prev_chunk, 1753 + (&(pginfo->u.usr.region->chunk_list)), 1754 + list); 1755 + return ret; 1756 + } 1757 + 1758 + int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo, 1759 + u32 number, 1760 + u64 *kpage) 1761 + { 1762 + int ret = 0; 1763 + struct ib_phys_buf *pbuf; 1764 + u64 num_hw, offs_hw; 1765 + u32 i = 0; 1766 + 1767 + /* loop over desired phys_buf_array entries */ 1768 + while (i < number) { 1769 + pbuf = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf; 1770 + num_hw = NUM_CHUNKS((pbuf->addr % EHCA_PAGESIZE) + 1771 + pbuf->size, EHCA_PAGESIZE); 1772 + offs_hw = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; 1773 + while (pginfo->next_hwpage < offs_hw + num_hw) { 1774 + /* sanity check */ 1775 + if ((pginfo->kpage_cnt >= pginfo->num_kpages) || 1776 + (pginfo->hwpage_cnt >= pginfo->num_hwpages)) { 1777 + ehca_gen_err("kpage_cnt >= num_kpages, " 1778 + "kpage_cnt=%lx num_kpages=%lx " 1779 + "hwpage_cnt=%lx " 1780 + "num_hwpages=%lx i=%x", 1781 + pginfo->kpage_cnt, 1782 + pginfo->num_kpages, 1783 + pginfo->hwpage_cnt, 1784 + pginfo->num_hwpages, i); 1785 + return -EFAULT; 1786 + } 1787 + *kpage = phys_to_abs( 1788 + (pbuf->addr & EHCA_PAGEMASK) 1789 + + (pginfo->next_hwpage * EHCA_PAGESIZE)); 1790 + if ( !(*kpage) && pbuf->addr ) { 1791 + ehca_gen_err("pbuf->addr=%lx " 1792 + "pbuf->size=%lx " 1793 + "next_hwpage=%lx", pbuf->addr, 1794 + pbuf->size, 1795 + pginfo->next_hwpage); 1796 + return -EFAULT; 1797 + } 1798 + (pginfo->hwpage_cnt)++; 1799 + (pginfo->next_hwpage)++; 1800 + if (pginfo->next_hwpage % 1801 + (PAGE_SIZE / EHCA_PAGESIZE) == 0) 1802 + (pginfo->kpage_cnt)++; 1803 + kpage++; 1804 + i++; 1805 + if (i >= number) break; 1806 + } 1807 + if (pginfo->next_hwpage >= offs_hw + num_hw) { 1808 + (pginfo->u.phy.next_buf)++; 1809 + pginfo->next_hwpage = 0; 1810 + } 1811 + } 1812 + return ret; 1813 + } 1814 + 1815 + int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo, 1816 + u32 number, 1817 + u64 *kpage) 1818 + { 1819 + int ret = 0; 1820 + u64 *fmrlist; 1821 + u32 i; 1822 + 1823 + /* loop over desired page_list entries */ 1824 + fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem; 1825 + for (i = 0; i < number; i++) { 1826 + *kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + 1933 1827 pginfo->next_hwpage * EHCA_PAGESIZE); 1934 - if ( !(*rpage) ) { 1828 + if ( !(*kpage) ) { 1935 1829 ehca_gen_err("*fmrlist=%lx fmrlist=%p " 1936 1830 "next_listelem=%lx next_hwpage=%lx", 1937 - *fmrlist, fmrlist, pginfo->u.fmr.next_listelem, 1831 + *fmrlist, fmrlist, 1832 + pginfo->u.fmr.next_listelem, 1938 1833 pginfo->next_hwpage); 1939 - ret = -EFAULT; 1940 - goto ehca_set_pagebuf_1_exit0; 1834 + return -EFAULT; 1941 1835 } 1942 1836 (pginfo->hwpage_cnt)++; 1943 1837 (pginfo->next_hwpage)++; 1838 + kpage++; 1944 1839 if (pginfo->next_hwpage % 1945 - (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { 1840 + (pginfo->u.fmr.fmr_pgsize / EHCA_PAGESIZE) == 0) { 1946 1841 (pginfo->kpage_cnt)++; 1947 1842 (pginfo->u.fmr.next_listelem)++; 1843 + fmrlist++; 1948 1844 pginfo->next_hwpage = 0; 1949 1845 } 1950 - } else { 1846 + } 1847 + return ret; 1848 + } 1849 + 1850 + /* setup page buffer from page info */ 1851 + int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo, 1852 + u32 number, 1853 + u64 *kpage) 1854 + { 1855 + int ret; 1856 + 1857 + switch (pginfo->type) { 1858 + case EHCA_MR_PGI_PHYS: 1859 + ret = ehca_set_pagebuf_phys(pginfo, number, kpage); 1860 + break; 1861 + case EHCA_MR_PGI_USER: 1862 + ret = ehca_set_pagebuf_user1(pginfo, number, kpage); 1863 + break; 1864 + case EHCA_MR_PGI_FMR: 1865 + ret = ehca_set_pagebuf_fmr(pginfo, number, kpage); 1866 + break; 1867 + default: 1951 1868 ehca_gen_err("bad pginfo->type=%x", pginfo->type); 1952 1869 ret = -EFAULT; 1953 - goto ehca_set_pagebuf_1_exit0; 1870 + break; 1954 1871 } 1955 - 1956 - ehca_set_pagebuf_1_exit0: 1957 - if (ret) 1958 - ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_kpages=%lx " 1959 - "num_hwpages=%lx next_buf=%lx next_hwpage=%lx rpage=%p " 1960 - "kpage_cnt=%lx hwpage_cnt=%lx next_listelem=%lx " 1961 - "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr, 1962 - pginfo, pginfo->type, pginfo->num_kpages, 1963 - pginfo->num_hwpages, pginfo->u.phy.next_buf, pginfo->next_hwpage, 1964 - rpage, pginfo->kpage_cnt, pginfo->hwpage_cnt, 1965 - pginfo->u.fmr.next_listelem, pginfo->u.usr.region, 1966 - pginfo->u.usr.next_chunk, pginfo->u.usr.next_nmap); 1967 1872 return ret; 1968 - } /* end ehca_set_pagebuf_1() */ 1873 + } /* end ehca_set_pagebuf() */ 1969 1874 1970 1875 /*----------------------------------------------------------------------*/ 1971 1876