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;
}
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;
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);
unsigned long *bank_bm_small;
u32 num_large_banks;
u32 num_small_banks;
+ u16 align;
};
#endif
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;
phy_map[i] = SCSC_MIF_ABS_SMALL_BANK;
}
+ if (align)
+ *align = 1 << PLATFORM_MIF_SHIFT_SMAPPER_ADDR;
+
return 0;
}
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);
#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);
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;
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;
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;
}
}
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);
/* 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);