src/dpdk/drivers/net/ice/base/ice_acl_ctrl.c
static enum ice_status
ice_acl_alloc_partition(struct ice_hw *hw, struct ice_acl_scen *req)
{
	u16 start = 0, cnt = 0, off = 0;
	u16 width, r_entries, row;
	bool done = false;
	int dir;

	/* Determine the number of TCAMs each entry overlaps */
	width = DIVIDE_AND_ROUND_UP(req->width, ICE_AQC_ACL_KEY_WIDTH_BYTES);

	/* Check if we have enough TCAMs to accommodate the width */
	if (width > hw->acl_tbl->last_tcam - hw->acl_tbl->first_tcam + 1)
		return ICE_ERR_MAX_LIMIT;

	/* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */
	r_entries = ICE_ALIGN(req->num_entry, ICE_ACL_ENTRY_ALLOC_UNIT);

	/* To look for an available partition that can accommodate the request,
	 * the process first logically arranges available TCAMs in rows such
	 * that each row produces entries with the requested width. It then
	 * scans the TCAMs' available bitmap, one bit at a time, and
	 * accumulates contiguous available 64-entry chunks until there are
	 * enough of them or when all TCAM configurations have been checked.
	 *
	 * For width of 1 TCAM, the scanning process starts from the top most
	 * TCAM, and goes downward. Available bitmaps are examined from LSB
	 * to MSB.
	 *
	 * For width of multiple TCAMs, the process starts from the bottom-most
	 * row of TCAMs, and goes upward. Available bitmaps are examined from
	 * the MSB to the LSB.
	 *
	 * To make sure that adjacent TCAMs can be logically arranged in the
	 * same row, the scanning process may have multiple passes. In each
	 * pass, the first TCAM of the bottom-most row is displaced by one
	 * additional TCAM. The width of the row and the number of the TCAMs
	 * available determine the number of passes. When the displacement is
	 * more than the size of width, the TCAM row configurations will
	 * repeat. The process will terminate when the configurations repeat.
	 *
	 * Available partitions can span more than one row of TCAMs.
	 */
	if (width == 1) {
		row = hw->acl_tbl->first_tcam;
		dir = 1;
	} else {
		/* Start with the bottom-most row, and scan for available
		 * entries upward
		 */
		row = hw->acl_tbl->last_tcam + 1 - width;
		dir = -1;
	}

	do {
		u16 i;

		/* Scan all 64-entry chunks, one chunk at a time, in the
		 * current TCAM row
		 */
		for (i = 0;
		     i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries;
		     i++) {
			bool avail = true;
			u16 w, p;

			/* Compute the cumulative available mask across the
			 * TCAM row to determine if the current 64-entry chunk
			 * is available.
			 */
			p = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1;
			for (w = row; w < row + width && avail; w++) {
				u16 b;

				b = (w * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + p;
				avail &= ice_is_bit_set(hw->acl_tbl->avail, b);
			}

			if (!avail) {
				cnt = 0;
			} else {
				/* Compute the starting index of the newly
				 * found partition. When 'dir' is negative, the
				 * scan processes is going upward. If so, the
				 * starting index needs to be updated for every
				 * available 64-entry chunk found.
				 */
				if (!cnt || dir < 0)
					start = (row * ICE_AQC_ACL_TCAM_DEPTH) +
						(p * ICE_ACL_ENTRY_ALLOC_UNIT);
				cnt += ICE_ACL_ENTRY_ALLOC_UNIT;
			}
		}

		if (cnt >= r_entries) {
			req->start = start;
			req->num_entry = r_entries;
			req->end = ice_acl_tbl_calc_end_idx(start, r_entries,
							    width);
			break;
		}

		row = dir > 0 ? row + width : row - width;
		if (row > hw->acl_tbl->last_tcam ||
		    row < hw->acl_tbl->first_tcam) {
			/* All rows have been checked. Increment 'off' that
			 * will help yield a different TCAM configuration in
			 * which adjacent TCAMs can be alternatively in the
			 * same row.
			 */
			off++;

			/* However, if the new 'off' value yields previously
			 * checked configurations, then exit.
			 */
			if (off >= width)
				done = true;
			else
				row = dir > 0 ? off :
					hw->acl_tbl->last_tcam + 1 - off -
					width;
		}
	} while (!done);

	return cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT;
}
/**
 * ice_acl_alloc_partition - Allocate a partition from the ACL table
 * @hw: pointer to the hardware structure
 * @req: info of partition being allocated
 */
Allocate a partition from the ACL table
@hw: pointer to the hardware structure
@req: info of partition being allocated
Allocate a partition from the ACL table @hw : pointer to the hardware structure @req : info of partition being allocated
static enum ice_status
ice_acl_alloc_partition(struct ice_hw *hw, struct ice_acl_scen *req)
{
	u16 start = 0, cnt = 0, off = 0;
	u16 width, r_entries, row;
	bool done = false;
	int dir;
	width = DIVIDE_AND_ROUND_UP(req->width, ICE_AQC_ACL_KEY_WIDTH_BYTES);
	if (width > hw->acl_tbl->last_tcam - hw->acl_tbl->first_tcam + 1)
		return ICE_ERR_MAX_LIMIT;
	r_entries = ICE_ALIGN(req->num_entry, ICE_ACL_ENTRY_ALLOC_UNIT);
	if (width == 1) {
		row = hw->acl_tbl->first_tcam;
		dir = 1;
	} else {
		row = hw->acl_tbl->last_tcam + 1 - width;
		dir = -1;
	}
	do {
		u16 i;
		for (i = 0;
		     i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries;
		     i++) {
			bool avail = true;
			u16 w, p;
			p = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1;
			for (w = row; w < row + width && avail; w++) {
				u16 b;
				b = (w * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + p;
				avail &= ice_is_bit_set(hw->acl_tbl->avail, b);
			}
			if (!avail) {
				cnt = 0;
			} else {
				if (!cnt || dir < 0)
					start = (row * ICE_AQC_ACL_TCAM_DEPTH) +
						(p * ICE_ACL_ENTRY_ALLOC_UNIT);
				cnt += ICE_ACL_ENTRY_ALLOC_UNIT;
			}
		}
		if (cnt >= r_entries) {
			req->start = start;
			req->num_entry = r_entries;
			req->end = ice_acl_tbl_calc_end_idx(start, r_entries,
							    width);
			break;
		}
		row = dir > 0 ? row + width : row - width;
		if (row > hw->acl_tbl->last_tcam ||
		    row < hw->acl_tbl->first_tcam) {
			off++;
			if (off >= width)
				done = true;
			else
				row = dir > 0 ? off :
					hw->acl_tbl->last_tcam + 1 - off -
					width;
		}
	} while (!done);
	return cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT;
}
static enum ice_status ice_acl_alloc_partition ( struct ice_hw * hw , struct ice_acl_scen * req ) { u16 start = 0 , cnt = 0 , off = 0 ; u16 width , r_entries , row ; bool done = false ; int dir ; width = DIVIDE_AND_ROUND_UP ( req -> width , ICE_AQC_ACL_KEY_WIDTH_BYTES ) ; if ( width > hw -> acl_tbl -> last_tcam - hw -> acl_tbl -> first_tcam + 1 ) return ICE_ERR_MAX_LIMIT ; r_entries = ICE_ALIGN ( req -> num_entry , ICE_ACL_ENTRY_ALLOC_UNIT ) ; if ( width == 1 ) { row = hw -> acl_tbl -> first_tcam ; dir = 1 ; } else { row = hw -> acl_tbl -> last_tcam + 1 - width ; dir = -1 ; } do { u16 i ; for ( i = 0 ; i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries ; i ++ ) { bool avail = true ; u16 w , p ; p = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1 ; for ( w = row ; w < row + width && avail ; w ++ ) { u16 b ; b = ( w * ICE_AQC_MAX_TCAM_ALLOC_UNITS ) + p ; avail &= ice_is_bit_set ( hw -> acl_tbl -> avail , b ) ; } if ( ! avail ) { cnt = 0 ; } else { if ( ! cnt || dir < 0 ) start = ( row * ICE_AQC_ACL_TCAM_DEPTH ) + ( p * ICE_ACL_ENTRY_ALLOC_UNIT ) ; cnt += ICE_ACL_ENTRY_ALLOC_UNIT ; } } if ( cnt >= r_entries ) { req -> start = start ; req -> num_entry = r_entries ; req -> end = ice_acl_tbl_calc_end_idx ( start , r_entries , width ) ; break ; } row = dir > 0 ? row + width : row - width ; if ( row > hw -> acl_tbl -> last_tcam || row < hw -> acl_tbl -> first_tcam ) { off ++ ; if ( off >= width ) done = true ; else row = dir > 0 ? off : hw -> acl_tbl -> last_tcam + 1 - off - width ; } } while ( ! done ) ; return cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT ; }
ice_acl_alloc_partition - Allocate a partition from the ACL table
 @hw: pointer to the hardware structure
 @req: info of partition being allocated
ice_acl_alloc_partition - Allocate a partition from the ACL table @hw : pointer to the hardware structure @req : info of partition being allocated
/* Determine the number of TCAMs each entry overlaps */ /* Check if we have enough TCAMs to accommodate the width */ /* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */ /* To look for an available partition that can accommodate the request,
	 * the process first logically arranges available TCAMs in rows such
	 * that each row produces entries with the requested width. It then
	 * scans the TCAMs' available bitmap, one bit at a time, and
	 * accumulates contiguous available 64-entry chunks until there are
	 * enough of them or when all TCAM configurations have been checked.
	 *
	 * For width of 1 TCAM, the scanning process starts from the top most
	 * TCAM, and goes downward. Available bitmaps are examined from LSB
	 * to MSB.
	 *
	 * For width of multiple TCAMs, the process starts from the bottom-most
	 * row of TCAMs, and goes upward. Available bitmaps are examined from
	 * the MSB to the LSB.
	 *
	 * To make sure that adjacent TCAMs can be logically arranged in the
	 * same row, the scanning process may have multiple passes. In each
	 * pass, the first TCAM of the bottom-most row is displaced by one
	 * additional TCAM. The width of the row and the number of the TCAMs
	 * available determine the number of passes. When the displacement is
	 * more than the size of width, the TCAM row configurations will
	 * repeat. The process will terminate when the configurations repeat.
	 *
	 * Available partitions can span more than one row of TCAMs.
	 */ /* Start with the bottom-most row, and scan for available
		 * entries upward
		 */ /* Scan all 64-entry chunks, one chunk at a time, in the
		 * current TCAM row
		 */ /* Compute the cumulative available mask across the
			 * TCAM row to determine if the current 64-entry chunk
			 * is available.
			 */ /* Compute the starting index of the newly
				 * found partition. When 'dir' is negative, the
				 * scan processes is going upward. If so, the
				 * starting index needs to be updated for every
				 * available 64-entry chunk found.
				 */ /* All rows have been checked. Increment 'off' that
			 * will help yield a different TCAM configuration in
			 * which adjacent TCAMs can be alternatively in the
			 * same row.
			 */ /* However, if the new 'off' value yields previously
			 * checked configurations, then exit.
			 */