int avtab_alloc(struct avtab *h, u32 nrules) { u32 mask = 0; u32 shift = 0; u32 work = nrules; u32 nslot = 0; if (nrules == 0) goto avtab_alloc_out; while (work) { work = work >> 1; shift++; } if (shift > 2) shift = shift - 2; nslot = 1 << shift; if (nslot > MAX_AVTAB_HASH_BUCKETS) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot, GFP_KERNEL | __GFP_ZERO); if (!h->htable) return -ENOMEM; avtab_alloc_out: h->nel = 0; h->nslot = nslot; h->mask = mask; printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n", h->nslot, nrules); return 0; }
static struct flex_array *fa_alloc(size_t elem_size, size_t elem_count, gfp_t gfp) { struct flex_array *result; int err; result = flex_array_alloc(elem_size, elem_count, gfp); if (result) { err = flex_array_prealloc(result, 0, elem_count, gfp); if (err) { flex_array_free(result); result = NULL; } } return result; }
static struct flex_array *alloc_buckets(unsigned int n_buckets) { struct flex_array *buckets; int i, err; buckets = flex_array_alloc(sizeof(struct hlist_head *), n_buckets, GFP_KERNEL); if (!buckets) return NULL; err = flex_array_prealloc(buckets, 0, n_buckets, GFP_KERNEL); if (err) { flex_array_free(buckets); return NULL; } for (i = 0; i < n_buckets; i++) INIT_HLIST_HEAD((struct hlist_head *) flex_array_get(buckets, i)); return buckets; }
/** * Reads and parses the register descriptor. * * @fn - the function device we're working with * @desc - will be filled in with the parsed data * @address - the starting address for the register descriptor */ static int rmi_read_reg_descriptor(struct rmi_function *fn, struct rmi_reg_descriptor *desc, u16 address) { struct rmi_device *rmi_dev = fn->rmi_dev; int retval; u8 *buf; int i, j; int offset; int reg_offset = 0; int nr_regs; int reg; int bitpos; int lastbit; struct rmi_register_desc reg_desc; retval = rmi_read(rmi_dev, address, &desc->presence_size); if (retval < 0) return retval; address++; buf = devm_kzalloc(&fn->dev, desc->presence_size, GFP_KERNEL); if (!buf) return -ENOMEM; retval = rmi_read_block(rmi_dev, address, buf, desc->presence_size); if (retval < 0) goto exit; address++; desc->structure_size = buf[0]; offset = 1; if (desc->structure_size == 0) { desc->structure_size = buf[1] | (buf[2] << 8); offset += 2; } nr_regs = desc->presence_size - offset; desc->presence_bits = nr_regs * 8; desc->presence = devm_kzalloc(&fn->dev, BITS_TO_LONGS(desc->presence_bits)*sizeof(unsigned long), GFP_KERNEL); if (!desc->presence) { retval = -ENOMEM; goto exit; } bitpos = 0; for (j = 0; j < nr_regs; j++) { for (i = 0; i < 8; i++) { if (buf[offset] & (1 << i)) { set_bit(bitpos, desc->presence); lastbit = bitpos; } bitpos++; } offset++; } devm_kfree(&fn->dev, buf); buf = devm_kzalloc(&fn->dev, desc->structure_size, GFP_KERNEL); if (!buf) return -ENOMEM; desc->structure = flex_array_alloc(sizeof(struct rmi_register_desc), desc->presence_bits, GFP_KERNEL); if (!desc->structure) { retval = -ENOMEM; goto exit; } retval = rmi_read_block(rmi_dev, address, buf, desc->structure_size); if (retval < 0) goto exit; reg = find_first_bit(desc->presence, desc->presence_bits); offset = 0; while (reg < desc->presence_bits) { bool done = false; int base; reg_desc.nr_subpackets = 0; reg_desc.size = buf[offset]; reg_desc.offset = reg_offset; reg_offset += reg_desc.size; offset++; if (reg_desc.size == 0) { reg_desc.size = buf[offset] | (buf[offset+1] << 8); offset += 2; } if (reg_desc.size == 0) { reg_desc.size = buf[offset] | (buf[offset+1] << 8) | (buf[offset+2] << 16) | (buf[offset+3] << 24); offset += 4; } base = offset; while (!done) { reg_desc.nr_subpackets += 7; done = (buf[offset] & 0x80) == 0; offset++; } reg_desc.subpackets = devm_kzalloc(&fn->dev, BITS_TO_LONGS(reg_desc.nr_subpackets)*sizeof(unsigned long), GFP_KERNEL); if (!reg_desc.subpackets) { retval = -ENOMEM; goto exit; } offset = base; bitpos = 0; done = false; while (!done) { for (i = 0; i < 7; i++) { if (buf[offset] & (0x01 << i)) { set_bit(bitpos, reg_desc.subpackets); } bitpos++; } done = (buf[offset] & 0x80) == 0; offset++; } retval = flex_array_put(desc->structure, reg, ®_desc, GFP_KERNEL); if (retval) dev_warn(&fn->dev, "Failed to put reg %d structure info. Code: %d.\n", reg, retval); reg = find_next_bit(desc->presence, desc->presence_bits, reg+1); } retval = 0; exit: devm_kfree(&fn->dev, buf); return retval; }