Beispiel #1
0
/*
 *  ======== cmm_get_info ========
 *  Purpose:
 *      Return the current memory utilization information.
 */
int cmm_get_info(struct cmm_object *hcmm_mgr,
			OUT struct cmm_info *cmm_info_obj)
{
	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
	u32 ul_seg;
	int status = 0;
	struct cmm_allocator *altr;
	struct cmm_mnode *mnode_obj = NULL;

	DBC_REQUIRE(cmm_info_obj != NULL);

	if (!hcmm_mgr) {
		status = -EFAULT;
		return status;
	}
	mutex_lock(&cmm_mgr_obj->cmm_lock);
	cmm_info_obj->ul_num_gppsm_segs = 0;	/* # of SM segments */
	/* Total # of outstanding alloc */
	cmm_info_obj->ul_total_in_use_cnt = 0;
	/* min block size */
	cmm_info_obj->ul_min_block_size = cmm_mgr_obj->ul_min_block_size;
	/* check SM memory segments */
	for (ul_seg = 1; ul_seg <= CMM_MAXGPPSEGS; ul_seg++) {
		/* get the allocator object for this segment id */
		altr = get_allocator(cmm_mgr_obj, ul_seg);
		if (altr != NULL) {
			cmm_info_obj->ul_num_gppsm_segs++;
			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_pa =
			    altr->shm_base - altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].ul_total_seg_size =
			    altr->ul_dsp_size + altr->ul_sm_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_gpp_base_pa =
			    altr->shm_base;
			cmm_info_obj->seg_info[ul_seg - 1].ul_gpp_size =
			    altr->ul_sm_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_dsp_base_va =
			    altr->dw_dsp_base;
			cmm_info_obj->seg_info[ul_seg - 1].ul_dsp_size =
			    altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_va =
			    altr->dw_vm_base - altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt = 0;
			mnode_obj = (struct cmm_mnode *)
			    lst_first(altr->in_use_list_head);
			/* Count inUse blocks */
			while (mnode_obj) {
				cmm_info_obj->ul_total_in_use_cnt++;
				cmm_info_obj->seg_info[ul_seg -
						       1].ul_in_use_cnt++;
				/* next node. */
				mnode_obj = (struct cmm_mnode *)
				    lst_next(altr->in_use_list_head,
					     (struct list_head *)mnode_obj);
			}
		}
	}			/* end for */
	mutex_unlock(&cmm_mgr_obj->cmm_lock);
	return status;
}
Beispiel #2
0
/*
 *  ======== un_register_gppsm_seg ========
 *  Purpose:
 *      UnRegister the SM allocator by freeing all its resources and
 *      nulling cmm mgr table entry.
 *  Note:
 *      This routine is always called within cmm lock crit sect.
 */
static void un_register_gppsm_seg(struct cmm_allocator *psma)
{
	struct cmm_mnode *mnode_obj = NULL;
	struct cmm_mnode *next_node = NULL;

	DBC_REQUIRE(psma != NULL);
	if (psma->free_list_head != NULL) {
		/* free nodes on free list */
		mnode_obj = (struct cmm_mnode *)lst_first(psma->free_list_head);
		while (mnode_obj) {
			next_node =
			    (struct cmm_mnode *)lst_next(psma->free_list_head,
							 (struct list_head *)
							 mnode_obj);
			lst_remove_elem(psma->free_list_head,
					(struct list_head *)mnode_obj);
			kfree((void *)mnode_obj);
			/* next node. */
			mnode_obj = next_node;
		}
		kfree(psma->free_list_head);	/* delete freelist */
		/* free nodes on InUse list */
		mnode_obj =
		    (struct cmm_mnode *)lst_first(psma->in_use_list_head);
		while (mnode_obj) {
			next_node =
			    (struct cmm_mnode *)lst_next(psma->in_use_list_head,
							 (struct list_head *)
							 mnode_obj);
			lst_remove_elem(psma->in_use_list_head,
					(struct list_head *)mnode_obj);
			kfree((void *)mnode_obj);
			/* next node. */
			mnode_obj = next_node;
		}
		kfree(psma->in_use_list_head);	/* delete InUse list */
	}
	if ((void *)psma->dw_vm_base != NULL)
		MEM_UNMAP_LINEAR_ADDRESS((void *)psma->dw_vm_base);

	/* Free allocator itself */
	kfree(psma);
}
Beispiel #3
0
void
main (void)
{
  LIST *list;
  int done = 0;
  REC *rec;
  char line[80];

  list = lst_init ();

  printf ("Type a list of names and ages. Empty line quits\n\n");

  while (!done)
    {
      rec = lst_newnode (sizeof (REC));
      gets (line);
      if ((done = (line[0] == '\0')) != 1)
	{
	  strcpy (rec->name, line);
	  gets (line);
	  rec->age = atoi (line);
	  lst_insertafter (list, rec, LST_HEAD (list));
	}
    };

  printf ("\nThe list you typed in was:\n\n");

  for (rec = lst_first (list); rec; rec = lst_next (rec))
    printf ("Name: %s, Age: %d\n", rec->name, rec->age);

  printf ("\nSorting the list...\n\n");

  lst_mergesort (list, my_cmp);

  for (rec = lst_first (list); rec; rec = lst_next (rec))
    printf ("Name: %s, Age: %d\n", rec->name, rec->age);

  lst_kill (list, lst_freenode);
}
Beispiel #4
0
/*
 *  ======== dev_notify_clients ========
 *  Purpose:
 *      Notify all clients of this device of a change in device status.
 */
int dev_notify_clients(struct dev_object *hdev_obj, u32 ret)
{
	int status = 0;

	struct dev_object *dev_obj = hdev_obj;
	void *proc_obj;

	for (proc_obj = (void *)lst_first(dev_obj->proc_list);
	     proc_obj != NULL;
	     proc_obj = (void *)lst_next(dev_obj->proc_list,
					 (struct list_head *)proc_obj))
		proc_notify_clients(proc_obj, (u32) ret);

	return status;
}
Beispiel #5
0
/*
 *  ======== rmm_free ========
 */
bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size,
	      bool reserved)
{
	struct rmm_ovly_sect *sect;
	bool ret = true;

	DBC_REQUIRE(target);

	DBC_REQUIRE(reserved || segid < target->num_segs);
	DBC_REQUIRE(reserved || (dsp_addr >= target->seg_tab[segid].base &&
				 (dsp_addr + size) <= (target->seg_tab[segid].
						   base +
						   target->seg_tab[segid].
						   length)));

	/*
	 *  Free or unreserve memory.
	 */
	if (!reserved) {
		ret = free_block(target, segid, dsp_addr, size);
		if (ret)
			target->seg_tab[segid].number--;

	} else {
		/* Unreserve memory */
		sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
		while (sect != NULL) {
			if (dsp_addr == sect->addr) {
				DBC_ASSERT(size == sect->size);
				/* Remove from list */
				lst_remove_elem(target->ovly_list,
						(struct list_head *)sect);
				kfree(sect);
				break;
			}
			sect =
			    (struct rmm_ovly_sect *)lst_next(target->ovly_list,
							     (struct list_head
							      *)sect);
		}
		if (sect == NULL)
			ret = false;

	}
	return ret;
}
Beispiel #6
0
/*
 *  ======== cmm_free_buf ========
 *  Purpose:
 *      Free the given buffer.
 */
int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
			u32 ul_seg_id)
{
	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
	int status = -EFAULT;
	struct cmm_mnode *mnode_obj = NULL;
	struct cmm_allocator *allocator = NULL;
	struct cmm_attrs *pattrs;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(buf_pa != NULL);

	if (ul_seg_id == 0) {
		pattrs = &cmm_dfltalctattrs;
		ul_seg_id = pattrs->ul_seg_id;
	}
	if (!hcmm_mgr || !(ul_seg_id > 0)) {
		status = -EFAULT;
		return status;
	}
	/* get the allocator for this segment id */
	allocator = get_allocator(cmm_mgr_obj, ul_seg_id);
	if (allocator != NULL) {
		mutex_lock(&cmm_mgr_obj->cmm_lock);
		mnode_obj =
		    (struct cmm_mnode *)lst_first(allocator->in_use_list_head);
		while (mnode_obj) {
			if ((u32) buf_pa == mnode_obj->dw_pa) {
				/* Found it */
				lst_remove_elem(allocator->in_use_list_head,
						(struct list_head *)mnode_obj);
				/* back to freelist */
				add_to_free_list(allocator, mnode_obj);
				status = 0;	/* all right! */
				break;
			}
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->in_use_list_head,
				     (struct list_head *)mnode_obj);
		}
		mutex_unlock(&cmm_mgr_obj->cmm_lock);
	}
	return status;
}
Beispiel #7
0
/*
 * ====== get_free_block ========
 *  Purpose:
 *      Scan the free block list and return the first block that satisfies
 *      the size.
 */
static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
					u32 usize)
{
	if (allocator) {
		struct cmm_mnode *mnode_obj = (struct cmm_mnode *)
		    lst_first(allocator->free_list_head);
		while (mnode_obj) {
			if (usize <= (u32) mnode_obj->ul_size) {
				lst_remove_elem(allocator->free_list_head,
						(struct list_head *)mnode_obj);
				return mnode_obj;
			}
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->free_list_head,
				     (struct list_head *)mnode_obj);
		}
	}
	return NULL;
}
Beispiel #8
0
static _linkage_block_ *
_add_line_to_linkage_block_ (Line *line_to_add,
			     Line *linkage_block_line,
			     List *linkage_block_lst)
{
  _linkage_block_ *linkage_block;

  assert (line_to_add);
  assert (linkage_block_line);
  assert (linkage_block_lst);
  assert (!lst_is_empty (linkage_block_lst));
  assert (line_to_add -> scale < linkage_block_line -> scale);

  for (linkage_block = lst_first (linkage_block_lst);
       linkage_block && linkage_block -> line != linkage_block_line;
       linkage_block = lst_next (linkage_block_lst));
  if (linkage_block && linkage_block -> line == linkage_block_line)
    {
      lst_add (line_to_add, linkage_block -> candidate_line_lst);
      linkage_block -> nb_of_candidates ++;
    }

  return linkage_block;
}
Beispiel #9
0
/*
 *  ======== dev_remove_proc_object ========
 *  Purpose:
 *      Search for and remove a Proc object from the given list maintained
 *      by the DEV
 *  Parameters:
 *      p_proc_object:        Ptr to ProcObject to insert.
 *      dev_obj          Ptr to Dev Object where the list is.
 *  Returns:
 *      0:            If successful.
 *  Requires:
 *      List exists and is not empty
 *      proc_obj != 0
 *      hdev_obj is a valid Dev handle.
 *  Ensures:
 *  Details:
 *      List will be deleted when the DEV is destroyed.
 */
int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
{
	int status = -EPERM;
	struct list_head *cur_elem;
	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;

	DBC_REQUIRE(dev_obj);
	DBC_REQUIRE(proc_obj != 0);
	DBC_REQUIRE(dev_obj->proc_list != NULL);
	DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list));

	/* Search list for dev_obj: */
	for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL;
	     cur_elem = lst_next(dev_obj->proc_list, cur_elem)) {
		/* If found, remove it. */
		if ((u32) cur_elem == proc_obj) {
			lst_remove_elem(dev_obj->proc_list, cur_elem);
			status = 0;
			break;
		}
	}

	return status;
}
Beispiel #10
0
/*
 *  ======== rmm_alloc ========
 */
int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
		     u32 align, u32 *dsp_address, bool reserve)
{
	struct rmm_ovly_sect *sect;
	struct rmm_ovly_sect *prev_sect = NULL;
	struct rmm_ovly_sect *new_sect;
	u32 addr;
	int status = 0;

	DBC_REQUIRE(target);
	DBC_REQUIRE(dsp_address != NULL);
	DBC_REQUIRE(size > 0);
	DBC_REQUIRE(reserve || (target->num_segs > 0));
	DBC_REQUIRE(refs > 0);

	if (!reserve) {
		if (!alloc_block(target, segid, size, align, dsp_address)) {
			status = -ENOMEM;
		} else {
			/* Increment the number of allocated blocks in this
			 * segment */
			target->seg_tab[segid].number++;
		}
		goto func_end;
	}
	/* An overlay section - See if block is already in use. If not,
	 * insert into the list in ascending address size. */
	addr = *dsp_address;
	sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
	/*  Find place to insert new list element. List is sorted from
	 *  smallest to largest address. */
	while (sect != NULL) {
		if (addr <= sect->addr) {
			/* Check for overlap with sect */
			if ((addr + size > sect->addr) || (prev_sect &&
							   (prev_sect->addr +
							    prev_sect->size >
							    addr))) {
				status = -ENXIO;
			}
			break;
		}
		prev_sect = sect;
		sect = (struct rmm_ovly_sect *)lst_next(target->ovly_list,
							(struct list_head *)
							sect);
	}
	if (!status) {
		/* No overlap - allocate list element for new section. */
		new_sect = kzalloc(sizeof(struct rmm_ovly_sect), GFP_KERNEL);
		if (new_sect == NULL) {
			status = -ENOMEM;
		} else {
			lst_init_elem((struct list_head *)new_sect);
			new_sect->addr = addr;
			new_sect->size = size;
			new_sect->page = segid;
			if (sect == NULL) {
				/* Put new section at the end of the list */
				lst_put_tail(target->ovly_list,
					     (struct list_head *)new_sect);
			} else {
				/* Put new section just before sect */
				lst_insert_before(target->ovly_list,
						  (struct list_head *)new_sect,
						  (struct list_head *)sect);
			}
		}
	}
func_end:
	return status;
}
Beispiel #11
0
/*
 *  ======== add_to_free_list ========
 *  Purpose:
 *      Coelesce node into the freelist in ascending size order.
 */
static void add_to_free_list(struct cmm_allocator *allocator,
			     struct cmm_mnode *pnode)
{
	struct cmm_mnode *node_prev = NULL;
	struct cmm_mnode *node_next = NULL;
	struct cmm_mnode *mnode_obj;
	u32 dw_this_pa;
	u32 dw_next_pa;

	DBC_REQUIRE(pnode != NULL);
	DBC_REQUIRE(allocator != NULL);
	dw_this_pa = pnode->dw_pa;
	dw_next_pa = NEXT_PA(pnode);
	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
	while (mnode_obj) {
		if (dw_this_pa == NEXT_PA(mnode_obj)) {
			/* found the block ahead of this one */
			node_prev = mnode_obj;
		} else if (dw_next_pa == mnode_obj->dw_pa) {
			node_next = mnode_obj;
		}
		if ((node_prev == NULL) || (node_next == NULL)) {
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->free_list_head,
				     (struct list_head *)mnode_obj);
		} else {
			/* got 'em */
			break;
		}
	}			/* while */
	if (node_prev != NULL) {
		/* combine with previous block */
		lst_remove_elem(allocator->free_list_head,
				(struct list_head *)node_prev);
		/* grow node to hold both */
		pnode->ul_size += node_prev->ul_size;
		pnode->dw_pa = node_prev->dw_pa;
		pnode->dw_va = node_prev->dw_va;
		/* place node on mgr nodeFreeList */
		delete_node((struct cmm_object *)allocator->hcmm_mgr,
			    node_prev);
	}
	if (node_next != NULL) {
		/* combine with next block */
		lst_remove_elem(allocator->free_list_head,
				(struct list_head *)node_next);
		/* grow da node */
		pnode->ul_size += node_next->ul_size;
		/* place node on mgr nodeFreeList */
		delete_node((struct cmm_object *)allocator->hcmm_mgr,
			    node_next);
	}
	/* Now, let's add to freelist in increasing size order */
	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
	while (mnode_obj) {
		if (pnode->ul_size <= mnode_obj->ul_size)
			break;

		/* next node. */
		mnode_obj =
		    (struct cmm_mnode *)lst_next(allocator->free_list_head,
						 (struct list_head *)mnode_obj);
	}
	/* if mnode_obj is NULL then add our pnode to the end of the freelist */
	if (mnode_obj == NULL) {
		lst_put_tail(allocator->free_list_head,
			     (struct list_head *)pnode);
	} else {
		/* insert our node before the current traversed node */
		lst_insert_before(allocator->free_list_head,
				  (struct list_head *)pnode,
				  (struct list_head *)mnode_obj);
	}
}