From: Albert Cano Date: Fri, 1 Jun 2018 08:29:29 +0000 (+0100) Subject: [9610] wlbt: SMAPPER. Check DMA addr alignment X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=34f6bc20d44c6f520633832d2a25d4e427872e77;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [9610] wlbt: SMAPPER. Check DMA addr alignment Since SMAPPER bank entry base address forces alignment (i.e. 2048 octets), hip4_smapper alloc should validate the dma buffer (phys address) before setting the entry. Usually skb/dma allocation will 'guarantee' 4k alignment unless SLUB/SLAB debug is enabled. Extended the smapper api to get the aligment from platform device virtual implementation Change-Id: Ic03f952d029efad7c60281d33d6915470072a3b5 SCSC-Bug-Id: SSB-40382 Signed-off-by: Albert Cano --- diff --git a/drivers/misc/samsung/scsc/mifsmapper.c b/drivers/misc/samsung/scsc/mifsmapper.c index 7d932719a1c4..924459c3c688 100644 --- a/drivers/misc/samsung/scsc/mifsmapper.c +++ b/drivers/misc/samsung/scsc/mifsmapper.c @@ -49,7 +49,7 @@ int mifsmapper_init(struct mifsmapper *smapper, struct scsc_mif_abs *mif) spin_lock_init(&smapper->lock); /* Get physical mapping of the banks */ - if (mif->mif_smapper_get_mapping(mif, phy_map)) { + if (mif->mif_smapper_get_mapping(mif, phy_map, &smapper->align)) { SCSC_TAG_ERR(MIF, "SMAPPER is not present\n"); return -EINVAL; } @@ -100,6 +100,11 @@ int mifsmapper_init(struct mifsmapper *smapper, struct scsc_mif_abs *mif) return 0; } +u16 mifsmapper_get_alignment(struct mifsmapper *smapper) +{ + return smapper->align; +} + int mifsmapper_alloc_bank(struct mifsmapper *smapper, bool large_bank, u32 entry_size, u16 *entries) { struct mifsmapper_bank *bank; diff --git a/drivers/misc/samsung/scsc/mifsmapper.h b/drivers/misc/samsung/scsc/mifsmapper.h index ed75469c2093..715f1f5503a8 100644 --- a/drivers/misc/samsung/scsc/mifsmapper.h +++ b/drivers/misc/samsung/scsc/mifsmapper.h @@ -13,6 +13,7 @@ struct scsc_mif_abs; struct mutex; int mifsmapper_init(struct mifsmapper *smapper, struct scsc_mif_abs *mif); +u16 mifsmapper_get_alignment(struct mifsmapper *smapper); int mifsmapper_alloc_bank(struct mifsmapper *smapper, bool large_bank, u32 entry_size, u16 *entries); int mifsmapper_free_bank(struct mifsmapper *smapper, u8 bank); int mifsmapper_get_entries(struct mifsmapper *smapper, u8 bank, u8 num_entries, u8 *entr); @@ -48,5 +49,6 @@ struct mifsmapper { unsigned long *bank_bm_small; u32 num_large_banks; u32 num_small_banks; + u16 align; }; #endif diff --git a/drivers/misc/samsung/scsc/platform_mif.c b/drivers/misc/samsung/scsc/platform_mif.c index 292e9fe34aa3..85daccfbfad4 100755 --- a/drivers/misc/samsung/scsc/platform_mif.c +++ b/drivers/misc/samsung/scsc/platform_mif.c @@ -228,8 +228,11 @@ inline u32 platform_mif_reg_read_smapper(struct platform_mif *platform, u16 offs return readl(platform->smapper_base + offset); } +#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ +#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* End address aligment */ + /* Platform is responsible to give the phys mapping of the SMAPPER maps */ -static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map) +static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align) { struct platform_mif *platform = platform_mif_from_mif_abs(interface); u8 i; @@ -246,6 +249,9 @@ static int platform_mif_smapper_get_mapping(struct scsc_mif_abs *interface, u8 * phy_map[i] = SCSC_MIF_ABS_SMALL_BANK; } + if (align) + *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR; + return 0; } @@ -281,9 +287,6 @@ static u8 platform_mif_smapper_granularity_to_bits(u32 granularity) return 7; } -#define PLATFORM_MIF_SHIFT_SMAPPER_ADDR 11 /* From 36 bits addres to 25 bits */ -#define PLATFORM_MIF_SHIFT_SMAPPER_END 4 /* From 36 bits addres to 25 bits */ - static u32 platform_mif_smapper_get_bank_base_address(struct scsc_mif_abs *interface, u8 bank) { struct platform_mif *platform = platform_mif_from_mif_abs(interface); diff --git a/drivers/misc/samsung/scsc/scsc_mif_abs.h b/drivers/misc/samsung/scsc/scsc_mif_abs.h index 27f767ccbfdf..8ce8caa15b51 100644 --- a/drivers/misc/samsung/scsc/scsc_mif_abs.h +++ b/drivers/misc/samsung/scsc/scsc_mif_abs.h @@ -187,7 +187,7 @@ struct scsc_mif_abs { #ifdef CONFIG_SCSC_SMAPPER /* SMAPPER */ - int (*mif_smapper_get_mapping)(struct scsc_mif_abs *interface, u8 *phy_map); + int (*mif_smapper_get_mapping)(struct scsc_mif_abs *interface, u8 *phy_map, u16 *align); int (*mif_smapper_get_bank_info)(struct scsc_mif_abs *interface, u8 bank, struct scsc_mif_smapper_info *bank_info); int (*mif_smapper_write_sram)(struct scsc_mif_abs *interface, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr); void (*mif_smapper_configure)(struct scsc_mif_abs *interface, u32 granularity); diff --git a/drivers/misc/samsung/scsc/scsc_service.c b/drivers/misc/samsung/scsc/scsc_service.c index 1bc076908119..27fbcbc390e8 100755 --- a/drivers/misc/samsung/scsc/scsc_service.c +++ b/drivers/misc/samsung/scsc/scsc_service.c @@ -887,6 +887,13 @@ int scsc_service_force_panic(struct scsc_service *service) EXPORT_SYMBOL(scsc_service_force_panic); #ifdef CONFIG_SCSC_SMAPPER +u16 scsc_service_get_alignment(struct scsc_service *service) +{ + struct scsc_mx *mx = service->mx; + + return mifsmapper_get_alignment(scsc_mx_get_smapper(mx)); +} + int scsc_service_mifsmapper_alloc_bank(struct scsc_service *service, bool large_bank, u32 entry_size, u16 *entries) { struct scsc_mx *mx = service->mx; diff --git a/drivers/net/wireless/scsc/hip4_smapper.c b/drivers/net/wireless/scsc/hip4_smapper.c index c73b056c929b..f6d9c8a4ebcf 100644 --- a/drivers/net/wireless/scsc/hip4_smapper.c +++ b/drivers/net/wireless/scsc/hip4_smapper.c @@ -38,6 +38,7 @@ static int hip4_smapper_alloc_bank(struct slsi_dev *sdev, struct hip4_priv *priv for (i = 0; i < bank->entries; i++) bank->skbuff[i] = NULL; + bank->align = scsc_service_get_alignment(sdev->service); bank->in_use = true; return 0; @@ -71,6 +72,15 @@ static int hip4_smapper_allocate_skb_buffers(struct slsi_dev *sdev, struct hip4_ slsi_kfree_skb(skb); return err; } + + /* Check alignment */ + if (!IS_ALIGNED(bank->skbuff_dma[i], bank->align)) { + SLSI_DBG4_NODEV(SLSI_SMAPPER, "Phys address: 0x%x not %d aligned. Unmap memory and return error\n", bank->skbuff_dma[i], bank->align); + dma_unmap_single(sdev->dev, bank->skbuff_dma[i], bank->entry_size, DMA_FROM_DEVICE); + slsi_kfree_skb(skb); + bank->skbuff_dma[i] = 0; + return -ENOMEM; + } bank->skbuff[i] = skb; } } diff --git a/drivers/net/wireless/scsc/hip4_smapper.h b/drivers/net/wireless/scsc/hip4_smapper.h index df2958e17e1a..37d54ca5d293 100644 --- a/drivers/net/wireless/scsc/hip4_smapper.h +++ b/drivers/net/wireless/scsc/hip4_smapper.h @@ -83,6 +83,7 @@ struct hip4_smapper_bank { struct sk_buff **skbuff; dma_addr_t *skbuff_dma; struct hip4_smapper_control_entry *entry; + u16 align; }; int hip4_smapper_init(struct slsi_dev *sdev, struct slsi_hip4 *hip); diff --git a/include/scsc/scsc_mx.h b/include/scsc/scsc_mx.h index 38cbddddd150..0c17b3fcbee8 100755 --- a/include/scsc/scsc_mx.h +++ b/include/scsc/scsc_mx.h @@ -219,6 +219,8 @@ int scsc_service_mifsmapper_free_entries(struct scsc_service *service, u8 bank, /* Program SRAM entry */ int scsc_service_mifsmapper_write_sram(struct scsc_service *service, u8 bank, u8 num_entries, u8 first_entry, dma_addr_t *addr); u32 scsc_service_mifsmapper_get_bank_base_address(struct scsc_service *service, u8 bank); +/* Get SMAPPER aligment */ +u16 scsc_service_get_alignment(struct scsc_service *service); #endif int scsc_service_pm_qos_add_request(struct scsc_service *service, enum scsc_qos_config config);