mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
IOMMU Updates for Linux 3.11
A few updates this time, most important and exiciting (to me) is:
* The new ARM SMMU driver. This is a common IOMMU driver that will
hopefully be used in a lot of upcoming ARM chips. So the mess in the
past where every SOC had its own IOMMU will be over.
Besides that:
* Some important fixes in the IOMMU unmap path. There are fixes in the
common code and also in the AMD IOMMU driver.
* Other random fixes
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
iQIcBAABAgAGBQJR2nDJAAoJECvwRC2XARrjumoQAKOW6D+45grEWsS4Ashf8GKe
PYzaMgmcBZdg+wGTVdxDI95KtYHq0xzKF+j5Wccy4qIOL8Ca38eqt5evjdYc0LYC
NWDPbuwoOHldDF6DoAZxhl1O0vguAA7h9WRKCvDDuNb9BUyEmcNOfBUSddgLhyOX
+PzLZ5s7bqIIOZ7BCMTn8nMC1wi8dq6l3OOGkvlwVm45X9cQ0LCm2DY3r8cvlLEW
FobxVk3B8qo0eE2NEjf4WZbScjPlk5sn4EIhA/5BrDKRZCbe9qL84HRGKD2zya78
bZlKiLyYkdI7PZbfp0qiFyLVnIA3ILPUUwiUgEnXKaQskiQsHE4VI66j2qiG0wym
bTK+MYc+8Ys6GDGrKRa7/yEN6N8dc06cai+UWiAemie8HhsP1lOHSDhmiznyx29i
s5u0HSrQq61epa3Juz31Ou5n6x1QU6zq6tSA6muXmPq5Md8DnwaL63nd+9WXHdns
te64asNo5Wn1ZXA24Gv51NlGRfRmUYvp9inPBBqjRggNCQdimynWYwVJfwQ7AjjB
RXfCxpjJZBsK661KrRvwAJKW1Q2RBHJCAaGSchkqRgcNRW/cTzE7JSg/wQ4XrdoS
X0uxl8Jobp348885FIveCGmZL5Lcq3EMtiGRhvNR1Mc9oeGhEijC31ve8pydvKrT
OF02muOXJ7matfR+dmkz
=oJr3
-----END PGP SIGNATURE-----
Merge tag 'iommu-updates-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel:
"A few updates this time, most important and exiciting (to me) is:
- The new ARM SMMU driver. This is a common IOMMU driver that will
hopefully be used in a lot of upcoming ARM chips. So the mess in
the past where every SOC had its own IOMMU will be over.
Besides that:
- Some important fixes in the IOMMU unmap path. There are fixes in
the common code and also in the AMD IOMMU driver.
- Other random fixes"
* tag 'iommu-updates-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
MAINTAINERS: add entry for ARM system MMU driver
iommu/arm: Add support for ARM Ltd. System MMU architecture
documentation/iommu: Add description of ARM System MMU binding
iommu: Use %pa and %zx instead of casting
iommu/amd: Only unmap large pages from the first pte
iommu: Fix compiler warning on pr_debug
iommu/amd: Fix memory leak in free_pagetable
iommu: Split iommu_unmaps
iommu/{vt-d,amd}: Remove multifunction assumption around grouping
iommu/omap: fix checkpatch warnings in omap iommu code
iommu/omap: fix printk formats for dma_addr_t
iommu/vt-d: DMAR reporting table needs at least one DRHD
iommu/vt-d: Downgrade the warning if enabling irq remapping fails
This commit is contained in:
commit
6664565681
13 changed files with 2212 additions and 90 deletions
|
|
@ -269,4 +269,17 @@ config SPAPR_TCE_IOMMU
|
|||
Enables bits of IOMMU API required by VFIO. The iommu_ops
|
||||
is not implemented as it is not necessary for VFIO.
|
||||
|
||||
config ARM_SMMU
|
||||
bool "ARM Ltd. System MMU (SMMU) Support"
|
||||
depends on ARM64 || (ARM_LPAE && OF)
|
||||
select IOMMU_API
|
||||
select ARM_DMA_USE_IOMMU if ARM
|
||||
help
|
||||
Support for implementations of the ARM System MMU architecture
|
||||
versions 1 and 2. The driver supports both v7l and v8l table
|
||||
formats with 4k and 64k page sizes.
|
||||
|
||||
Say Y here if your SoC includes an IOMMU device implementing
|
||||
the ARM SMMU architecture.
|
||||
|
||||
endif # IOMMU_SUPPORT
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ obj-$(CONFIG_OF_IOMMU) += of_iommu.o
|
|||
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
|
||||
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
|
||||
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
|
||||
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
|
||||
obj-$(CONFIG_DMAR_TABLE) += dmar.o
|
||||
obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
|
||||
obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
|
||||
|
|
|
|||
|
|
@ -287,14 +287,27 @@ static struct pci_dev *get_isolation_root(struct pci_dev *pdev)
|
|||
|
||||
/*
|
||||
* If it's a multifunction device that does not support our
|
||||
* required ACS flags, add to the same group as function 0.
|
||||
* required ACS flags, add to the same group as lowest numbered
|
||||
* function that also does not suport the required ACS flags.
|
||||
*/
|
||||
if (dma_pdev->multifunction &&
|
||||
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))
|
||||
swap_pci_ref(&dma_pdev,
|
||||
pci_get_slot(dma_pdev->bus,
|
||||
PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),
|
||||
0)));
|
||||
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
|
||||
u8 i, slot = PCI_SLOT(dma_pdev->devfn);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
struct pci_dev *tmp;
|
||||
|
||||
tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
|
||||
if (!tmp)
|
||||
continue;
|
||||
|
||||
if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
|
||||
swap_pci_ref(&dma_pdev, tmp);
|
||||
break;
|
||||
}
|
||||
pci_dev_put(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices on the root bus go through the iommu. If that's not us,
|
||||
|
|
@ -1484,6 +1497,10 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom,
|
|||
|
||||
/* Large PTE found which maps this address */
|
||||
unmap_size = PTE_PAGE_SIZE(*pte);
|
||||
|
||||
/* Only unmap from the first pte in the page */
|
||||
if ((unmap_size - 1) & bus_addr)
|
||||
break;
|
||||
count = PAGE_SIZE_PTE_COUNT(unmap_size);
|
||||
for (i = 0; i < count; i++)
|
||||
pte[i] = 0ULL;
|
||||
|
|
@ -1493,7 +1510,7 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom,
|
|||
unmapped += unmap_size;
|
||||
}
|
||||
|
||||
BUG_ON(!is_power_of_2(unmapped));
|
||||
BUG_ON(unmapped && !is_power_of_2(unmapped));
|
||||
|
||||
return unmapped;
|
||||
}
|
||||
|
|
@ -1893,34 +1910,59 @@ static void domain_id_free(int id)
|
|||
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
|
||||
}
|
||||
|
||||
#define DEFINE_FREE_PT_FN(LVL, FN) \
|
||||
static void free_pt_##LVL (unsigned long __pt) \
|
||||
{ \
|
||||
unsigned long p; \
|
||||
u64 *pt; \
|
||||
int i; \
|
||||
\
|
||||
pt = (u64 *)__pt; \
|
||||
\
|
||||
for (i = 0; i < 512; ++i) { \
|
||||
if (!IOMMU_PTE_PRESENT(pt[i])) \
|
||||
continue; \
|
||||
\
|
||||
p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \
|
||||
FN(p); \
|
||||
} \
|
||||
free_page((unsigned long)pt); \
|
||||
}
|
||||
|
||||
DEFINE_FREE_PT_FN(l2, free_page)
|
||||
DEFINE_FREE_PT_FN(l3, free_pt_l2)
|
||||
DEFINE_FREE_PT_FN(l4, free_pt_l3)
|
||||
DEFINE_FREE_PT_FN(l5, free_pt_l4)
|
||||
DEFINE_FREE_PT_FN(l6, free_pt_l5)
|
||||
|
||||
static void free_pagetable(struct protection_domain *domain)
|
||||
{
|
||||
int i, j;
|
||||
u64 *p1, *p2, *p3;
|
||||
unsigned long root = (unsigned long)domain->pt_root;
|
||||
|
||||
p1 = domain->pt_root;
|
||||
|
||||
if (!p1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 512; ++i) {
|
||||
if (!IOMMU_PTE_PRESENT(p1[i]))
|
||||
continue;
|
||||
|
||||
p2 = IOMMU_PTE_PAGE(p1[i]);
|
||||
for (j = 0; j < 512; ++j) {
|
||||
if (!IOMMU_PTE_PRESENT(p2[j]))
|
||||
continue;
|
||||
p3 = IOMMU_PTE_PAGE(p2[j]);
|
||||
free_page((unsigned long)p3);
|
||||
}
|
||||
|
||||
free_page((unsigned long)p2);
|
||||
switch (domain->mode) {
|
||||
case PAGE_MODE_NONE:
|
||||
break;
|
||||
case PAGE_MODE_1_LEVEL:
|
||||
free_page(root);
|
||||
break;
|
||||
case PAGE_MODE_2_LEVEL:
|
||||
free_pt_l2(root);
|
||||
break;
|
||||
case PAGE_MODE_3_LEVEL:
|
||||
free_pt_l3(root);
|
||||
break;
|
||||
case PAGE_MODE_4_LEVEL:
|
||||
free_pt_l4(root);
|
||||
break;
|
||||
case PAGE_MODE_5_LEVEL:
|
||||
free_pt_l5(root);
|
||||
break;
|
||||
case PAGE_MODE_6_LEVEL:
|
||||
free_pt_l6(root);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
free_page((unsigned long)p1);
|
||||
|
||||
domain->pt_root = NULL;
|
||||
}
|
||||
|
||||
static void free_gcr3_tbl_level1(u64 *tbl)
|
||||
|
|
|
|||
1969
drivers/iommu/arm-smmu.c
Normal file
1969
drivers/iommu/arm-smmu.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -309,6 +309,7 @@ parse_dmar_table(void)
|
|||
struct acpi_table_dmar *dmar;
|
||||
struct acpi_dmar_header *entry_header;
|
||||
int ret = 0;
|
||||
int drhd_count = 0;
|
||||
|
||||
/*
|
||||
* Do it again, earlier dmar_tbl mapping could be mapped with
|
||||
|
|
@ -347,6 +348,7 @@ parse_dmar_table(void)
|
|||
|
||||
switch (entry_header->type) {
|
||||
case ACPI_DMAR_TYPE_HARDWARE_UNIT:
|
||||
drhd_count++;
|
||||
ret = dmar_parse_one_drhd(entry_header);
|
||||
break;
|
||||
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
|
||||
|
|
@ -371,6 +373,8 @@ parse_dmar_table(void)
|
|||
|
||||
entry_header = ((void *)entry_header + entry_header->length);
|
||||
}
|
||||
if (drhd_count == 0)
|
||||
pr_warn(FW_BUG "No DRHD structure found in DMAR table\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4182,14 +4182,27 @@ static int intel_iommu_add_device(struct device *dev)
|
|||
|
||||
/*
|
||||
* If it's a multifunction device that does not support our
|
||||
* required ACS flags, add to the same group as function 0.
|
||||
* required ACS flags, add to the same group as lowest numbered
|
||||
* function that also does not suport the required ACS flags.
|
||||
*/
|
||||
if (dma_pdev->multifunction &&
|
||||
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))
|
||||
swap_pci_ref(&dma_pdev,
|
||||
pci_get_slot(dma_pdev->bus,
|
||||
PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),
|
||||
0)));
|
||||
!pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
|
||||
u8 i, slot = PCI_SLOT(dma_pdev->devfn);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
struct pci_dev *tmp;
|
||||
|
||||
tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
|
||||
if (!tmp)
|
||||
continue;
|
||||
|
||||
if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
|
||||
swap_pci_ref(&dma_pdev, tmp);
|
||||
break;
|
||||
}
|
||||
pci_dev_put(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Devices on the root bus go through the iommu. If that's not us,
|
||||
|
|
|
|||
|
|
@ -664,8 +664,7 @@ error:
|
|||
*/
|
||||
|
||||
if (x2apic_present)
|
||||
WARN(1, KERN_WARNING
|
||||
"Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
|
||||
pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -754,6 +754,38 @@ int iommu_domain_has_cap(struct iommu_domain *domain,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
|
||||
|
||||
static size_t iommu_pgsize(struct iommu_domain *domain,
|
||||
unsigned long addr_merge, size_t size)
|
||||
{
|
||||
unsigned int pgsize_idx;
|
||||
size_t pgsize;
|
||||
|
||||
/* Max page size that still fits into 'size' */
|
||||
pgsize_idx = __fls(size);
|
||||
|
||||
/* need to consider alignment requirements ? */
|
||||
if (likely(addr_merge)) {
|
||||
/* Max page size allowed by address */
|
||||
unsigned int align_pgsize_idx = __ffs(addr_merge);
|
||||
pgsize_idx = min(pgsize_idx, align_pgsize_idx);
|
||||
}
|
||||
|
||||
/* build a mask of acceptable page sizes */
|
||||
pgsize = (1UL << (pgsize_idx + 1)) - 1;
|
||||
|
||||
/* throw away page sizes not supported by the hardware */
|
||||
pgsize &= domain->ops->pgsize_bitmap;
|
||||
|
||||
/* make sure we're still sane */
|
||||
BUG_ON(!pgsize);
|
||||
|
||||
/* pick the biggest page */
|
||||
pgsize_idx = __fls(pgsize);
|
||||
pgsize = 1UL << pgsize_idx;
|
||||
|
||||
return pgsize;
|
||||
}
|
||||
|
||||
int iommu_map(struct iommu_domain *domain, unsigned long iova,
|
||||
phys_addr_t paddr, size_t size, int prot)
|
||||
{
|
||||
|
|
@ -775,45 +807,18 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
|
|||
* size of the smallest page supported by the hardware
|
||||
*/
|
||||
if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) {
|
||||
pr_err("unaligned: iova 0x%lx pa 0x%lx size 0x%lx min_pagesz "
|
||||
"0x%x\n", iova, (unsigned long)paddr,
|
||||
(unsigned long)size, min_pagesz);
|
||||
pr_err("unaligned: iova 0x%lx pa 0x%pa size 0x%zx min_pagesz 0x%x\n",
|
||||
iova, &paddr, size, min_pagesz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("map: iova 0x%lx pa 0x%lx size 0x%lx\n", iova,
|
||||
(unsigned long)paddr, (unsigned long)size);
|
||||
pr_debug("map: iova 0x%lx pa 0x%pa size 0x%zx\n", iova, &paddr, size);
|
||||
|
||||
while (size) {
|
||||
unsigned long pgsize, addr_merge = iova | paddr;
|
||||
unsigned int pgsize_idx;
|
||||
size_t pgsize = iommu_pgsize(domain, iova | paddr, size);
|
||||
|
||||
/* Max page size that still fits into 'size' */
|
||||
pgsize_idx = __fls(size);
|
||||
|
||||
/* need to consider alignment requirements ? */
|
||||
if (likely(addr_merge)) {
|
||||
/* Max page size allowed by both iova and paddr */
|
||||
unsigned int align_pgsize_idx = __ffs(addr_merge);
|
||||
|
||||
pgsize_idx = min(pgsize_idx, align_pgsize_idx);
|
||||
}
|
||||
|
||||
/* build a mask of acceptable page sizes */
|
||||
pgsize = (1UL << (pgsize_idx + 1)) - 1;
|
||||
|
||||
/* throw away page sizes not supported by the hardware */
|
||||
pgsize &= domain->ops->pgsize_bitmap;
|
||||
|
||||
/* make sure we're still sane */
|
||||
BUG_ON(!pgsize);
|
||||
|
||||
/* pick the biggest page */
|
||||
pgsize_idx = __fls(pgsize);
|
||||
pgsize = 1UL << pgsize_idx;
|
||||
|
||||
pr_debug("mapping: iova 0x%lx pa 0x%lx pgsize %lu\n", iova,
|
||||
(unsigned long)paddr, pgsize);
|
||||
pr_debug("mapping: iova 0x%lx pa 0x%pa pgsize 0x%zx\n",
|
||||
iova, &paddr, pgsize);
|
||||
|
||||
ret = domain->ops->map(domain, iova, paddr, pgsize, prot);
|
||||
if (ret)
|
||||
|
|
@ -850,27 +855,26 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
|
|||
* by the hardware
|
||||
*/
|
||||
if (!IS_ALIGNED(iova | size, min_pagesz)) {
|
||||
pr_err("unaligned: iova 0x%lx size 0x%lx min_pagesz 0x%x\n",
|
||||
iova, (unsigned long)size, min_pagesz);
|
||||
pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n",
|
||||
iova, size, min_pagesz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("unmap this: iova 0x%lx size 0x%lx\n", iova,
|
||||
(unsigned long)size);
|
||||
pr_debug("unmap this: iova 0x%lx size 0x%zx\n", iova, size);
|
||||
|
||||
/*
|
||||
* Keep iterating until we either unmap 'size' bytes (or more)
|
||||
* or we hit an area that isn't mapped.
|
||||
*/
|
||||
while (unmapped < size) {
|
||||
size_t left = size - unmapped;
|
||||
size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
|
||||
|
||||
unmapped_page = domain->ops->unmap(domain, iova, left);
|
||||
unmapped_page = domain->ops->unmap(domain, iova, pgsize);
|
||||
if (!unmapped_page)
|
||||
break;
|
||||
|
||||
pr_debug("unmapped: iova 0x%lx size %lx\n", iova,
|
||||
(unsigned long)unmapped_page);
|
||||
pr_debug("unmapped: iova 0x%lx size 0x%zx\n",
|
||||
iova, unmapped_page);
|
||||
|
||||
iova += unmapped_page;
|
||||
unmapped += unmapped_page;
|
||||
|
|
|
|||
|
|
@ -833,16 +833,15 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
|
|||
iopgd = iopgd_offset(obj, da);
|
||||
|
||||
if (!iopgd_is_table(*iopgd)) {
|
||||
dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
|
||||
"*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd);
|
||||
dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:px%08x\n",
|
||||
obj->name, errs, da, iopgd, *iopgd);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
iopte = iopte_offset(iopgd, da);
|
||||
|
||||
dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
|
||||
"pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
|
||||
iopte, *iopte);
|
||||
dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x pte:0x%p *pte:0x%08x\n",
|
||||
obj->name, errs, da, iopgd, *iopgd, iopte, *iopte);
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
|
@ -1235,14 +1234,16 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
|
|||
else if (iopte_is_large(*pte))
|
||||
ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
|
||||
else
|
||||
dev_err(dev, "bogus pte 0x%x, da 0x%lx", *pte, da);
|
||||
dev_err(dev, "bogus pte 0x%x, da 0x%llx", *pte,
|
||||
(unsigned long long)da);
|
||||
} else {
|
||||
if (iopgd_is_section(*pgd))
|
||||
ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
|
||||
else if (iopgd_is_super(*pgd))
|
||||
ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
|
||||
else
|
||||
dev_err(dev, "bogus pgd 0x%x, da 0x%lx", *pgd, da);
|
||||
dev_err(dev, "bogus pgd 0x%x, da 0x%llx", *pgd,
|
||||
(unsigned long long)da);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -95,4 +95,4 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
|
|||
#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da))
|
||||
|
||||
#define to_iommu(dev) \
|
||||
(struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
|
||||
((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev)))
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ static size_t sgtable_len(const struct sg_table *sgt)
|
|||
}
|
||||
|
||||
if (i && sg->offset) {
|
||||
pr_err("%s: sg[%d] offset not allowed in internal "
|
||||
"entries\n", __func__, i);
|
||||
pr_err("%s: sg[%d] offset not allowed in internal entries\n",
|
||||
__func__, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue