cregit-Linux how code gets into the kernel

Release 4.11 drivers/mcb/mcb-parse.c

Directory: drivers/mcb
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/mcb.h>

#include "mcb-internal.h"


struct mcb_parse_priv {
	
phys_addr_t mapbase;
	
void __iomem *base;
};


#define for_each_chameleon_cell(dtype, p)	\
	for ((dtype) = get_next_dtype((p));     \
             (dtype) != CHAMELEON_DTYPE_END;    \
             (dtype) = get_next_dtype((p)))


static inline uint32_t get_next_dtype(void __iomem *p) { uint32_t dtype; dtype = readl(p); return dtype >> 28; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Thumshirn27100.00%1100.00%
Total27100.00%1100.00%


static int chameleon_parse_bdd(struct mcb_bus *bus, struct chameleon_bar *cb, void __iomem *base) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Thumshirn2083.33%150.00%
Andreas Werner416.67%150.00%
Total24100.00%2100.00%


static int chameleon_parse_gdd(struct mcb_bus *bus, struct chameleon_bar *cb, void __iomem *base, int bar_count) { struct chameleon_gdd __iomem *gdd = (struct chameleon_gdd __iomem *) base; struct mcb_device *mdev; u32 dev_mapbase; u32 offset; u32 size; int ret; __le32 reg1; __le32 reg2; mdev = mcb_alloc_dev(bus); if (!mdev) return -ENOMEM; reg1 = readl(&gdd->reg1); reg2 = readl(&gdd->reg2); offset = readl(&gdd->offset); size = readl(&gdd->size); mdev->id = GDD_DEV(reg1); mdev->rev = GDD_REV(reg1); mdev->var = GDD_VAR(reg1); mdev->bar = GDD_BAR(reg2); mdev->group = GDD_GRP(reg2); mdev->inst = GDD_INS(reg2); /* * If the BAR is missing, dev_mapbase is zero, or if the * device is IO mapped we just print a warning and go on with the * next device, instead of completely stop the gdd parser */ if (mdev->bar > bar_count - 1) { pr_info("No BAR for 16z%03d\n", mdev->id); ret = 0; goto err; } dev_mapbase = cb[mdev->bar].addr; if (!dev_mapbase) { pr_info("BAR not assigned for 16z%03d\n", mdev->id); ret = 0; goto err; } if (dev_mapbase & 0x01) { pr_info("IO mapped Device (16z%03d) not yet supported\n", mdev->id); ret = 0; goto err; } pr_debug("Found a 16z%03d\n", mdev->id); mdev->irq.start = GDD_IRQ(reg1); mdev->irq.end = GDD_IRQ(reg1); mdev->irq.flags = IORESOURCE_IRQ; mdev->mem.start = dev_mapbase + offset; mdev->mem.end = mdev->mem.start + size - 1; mdev->mem.flags = IORESOURCE_MEM; mdev->is_added = false; ret = mcb_device_register(bus, mdev); if (ret < 0) goto err; return 0; err: mcb_free_dev(mdev); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Thumshirn26973.10%133.33%
Andreas Werner9926.90%266.67%
Total368100.00%3100.00%


static void chameleon_parse_bar(void __iomem *base, struct chameleon_bar *cb, int bar_count) { char __iomem *p = base; int i; /* skip reg1 */ p += sizeof(__le32); for (i = 0; i < bar_count; i++) { cb[i].addr = readl(p); cb[i].size = readl(p + 4); p += sizeof(struct chameleon_bar); } }

Contributors

PersonTokensPropCommitsCommitProp
Andreas Werner86100.00%1100.00%
Total86100.00%1100.00%


static int chameleon_get_bar(char __iomem **base, phys_addr_t mapbase, struct chameleon_bar **cb) { struct chameleon_bar *c; int bar_count; __le32 reg; u32 dtype; /* * For those devices which are not connected * to the PCI Bus (e.g. LPC) there is a bar * descriptor located directly after the * chameleon header. This header is comparable * to a PCI header. */ dtype = get_next_dtype(*base); if (dtype == CHAMELEON_DTYPE_BAR) { reg = readl(*base); bar_count = BAR_CNT(reg); if (bar_count <= 0 || bar_count > CHAMELEON_BAR_MAX) return -ENODEV; c = kcalloc(bar_count, sizeof(struct chameleon_bar), GFP_KERNEL); if (!c) return -ENOMEM; chameleon_parse_bar(*base, c, bar_count); *base += BAR_DESC_SIZE(bar_count); } else { c = kzalloc(sizeof(struct chameleon_bar), GFP_KERNEL); if (!c) return -ENOMEM; bar_count = 1; c->addr = mapbase; } *cb = c; return bar_count; }

Contributors

PersonTokensPropCommitsCommitProp
Andreas Werner16599.40%150.00%
Michael Moese10.60%150.00%
Total166100.00%2100.00%


int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, void __iomem *base) { struct chameleon_fpga_header *header; struct chameleon_bar *cb; char __iomem *p = base; int num_cells = 0; uint32_t dtype; int bar_count; int ret = 0; u32 hsize; hsize = sizeof(struct chameleon_fpga_header); header = kzalloc(hsize, GFP_KERNEL); if (!header) return -ENOMEM; /* Extract header information */ memcpy_fromio(header, p, hsize); /* We only support chameleon v2 at the moment */ header->magic = le16_to_cpu(header->magic); if (header->magic != CHAMELEONV2_MAGIC) { pr_err("Unsupported chameleon version 0x%x\n", header->magic); ret = -ENODEV; goto free_header; } p += hsize; bus->revision = header->revision; bus->model = header->model; bus->minor = header->minor; snprintf(bus->name, CHAMELEON_FILENAME_LEN + 1, "%s", header->filename); bar_count = chameleon_get_bar(&p, mapbase, &cb); if (bar_count < 0) goto free_header; for_each_chameleon_cell(dtype, p) { switch (dtype) { case CHAMELEON_DTYPE_GENERAL: ret = chameleon_parse_gdd(bus, cb, p, bar_count); if (ret < 0) goto free_bar; p += sizeof(struct chameleon_gdd); break; case CHAMELEON_DTYPE_BRIDGE: chameleon_parse_bdd(bus, cb, p); p += sizeof(struct chameleon_bdd); break; case CHAMELEON_DTYPE_END: break; default: pr_err("Invalid chameleon descriptor type 0x%x\n", dtype); ret = -EINVAL; goto free_bar; } num_cells++; } if (num_cells == 0) num_cells = -EINVAL; kfree(cb); kfree(header); return num_cells; free_bar: kfree(cb); free_header: kfree(header); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Johannes Thumshirn26279.64%266.67%
Andreas Werner6720.36%133.33%
Total329100.00%3100.00%

EXPORT_SYMBOL_GPL(chameleon_parse_cells);

Overall Contributors

PersonTokensPropCommitsCommitProp
Johannes Thumshirn62759.77%240.00%
Andreas Werner42140.13%240.00%
Michael Moese10.10%120.00%
Total1049100.00%5100.00%
Directory: drivers/mcb
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.