On Fri, Feb 24, 2023 at 12:36:51PM -0700, Jeffrey Hugo wrote: > > > +static int reserve_pages(unsigned long start_pfn, unsigned long nr_pages, > > > + bool reserve) > > > +{ > > > + unsigned long pfn; > > > + unsigned long end_pfn = start_pfn + nr_pages; > > > + struct page *page; > > > + > > > + for (pfn = start_pfn; pfn < end_pfn; pfn++) { > > > + if (!pfn_valid(pfn)) > > > + return -EINVAL; > > > + page = pfn_to_page(pfn); > > > + if (reserve) > > > + SetPageReserved(page); > > > + else > > > + ClearPageReserved(page); > > > > It is needed? Looks like taken from some legacy code. > > Required for remap_pfn_range(). PG_reserved is not required any longer for remap_pfn_range(), here is excerpt from comment from include/linux/page-flags.h : * Some PG_reserved pages will be excluded from the hibernation image. * PG_reserved does in general not hinder anybody from dumping or swapping * and is no longer required for remap_pfn_range(). ioremap might require it. * Consequently, PG_reserved for a page mapped into user space can indicate * the zero page, the vDSO, MMIO pages or device memory. > > > +static int copy_sgt(struct qaic_device *qdev, struct sg_table **sgt_out, > > > + struct sg_table *sgt_in, u64 size, u64 offset) > > > +{ > > > + int total_len, len, nents, offf = 0, offl = 0; > > > + struct scatterlist *sg, *sgn, *sgf, *sgl; > > > + struct sg_table *sgt; > > > + int ret, j; > > > + > > > + /* find out number of relevant nents needed for this mem */ > > > + total_len = 0; > > > + sgf = NULL; > > > + sgl = NULL; > > > + nents = 0; > > > + > > > + size = size ? size : PAGE_SIZE; > > > + for (sg = sgt_in->sgl; sg; sg = sg_next(sg)) { > > > + len = sg_dma_len(sg); > > > + > > > + if (!len) > > > + continue; > > > + if (offset >= total_len && offset < total_len + len) { > > > + sgf = sg; > > > + offf = offset - total_len; > > > + } > > > + if (sgf) > > > + nents++; > > > + if (offset + size >= total_len && > > > + offset + size <= total_len + len) { > > > + sgl = sg; > > > + offl = offset + size - total_len; > > > + break; > > > + } > > > + total_len += len; > > > + } > > > + > > > + if (!sgf || !sgl) { > > > + ret = -EINVAL; > > > + goto out; > > > + } > > > + > > > + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); > > > + if (!sgt) { > > > + ret = -ENOMEM; > > > + goto out; > > > + } > > > + > > > + ret = sg_alloc_table(sgt, nents, GFP_KERNEL); > > > + if (ret) > > > + goto free_sgt; > > > + > > > + /* copy relevant sg node and fix page and length */ > > > + sgn = sgf; > > > + for_each_sgtable_sg(sgt, sg, j) { > > > + memcpy(sg, sgn, sizeof(*sg)); > > > + if (sgn == sgf) { > > > + sg_dma_address(sg) += offf; This looks a bit suspicious. Are you sure you can modify sg->dma_address and still use it as valid value ? > > > + sg_dma_len(sg) -= offf; > > > + sg_set_page(sg, sg_page(sgn), > > > + sg_dma_len(sg), offf); > > > + } else { > > > + offf = 0; > > > + } > > > + if (sgn == sgl) { > > > + sg_dma_len(sg) = offl - offf; > > > + sg_set_page(sg, sg_page(sgn), > > > + offl - offf, offf); > > > + sg_mark_end(sg); > > > + break; > > > + } > > > + sgn = sg_next(sgn); > > > + } > > > > Why not use sg_copy_table() ? Overall copy_sgt() seems to be something > > that could be replaced by generic helper or at least simplify. > > I don't see "sg_copy_table" defined in 6.2. Because there is no such function in any kernel source. It was only my imagination, not sure right now how I came up with this function name :-/ Sorry about confusion. There are only sg_copy_{to,from}_buffer(), but not really useful in this case. > Are you suggesting renaming > this function? I guess I'm not quite understanding your comment here. Can > you elaborate? Renaming would be nice. I was thinking by simplifying it, not sure now if that's easy achievable, though. Regards Stanislaw