/* * Fill a DRP IE's allocation fields from a MAS bitmap. */ static void uwb_drp_ie_from_bm(struct uwb_ie_drp *drp_ie, struct uwb_mas_bm *mas) { int z, i, num_fields = 0, next = 0; struct uwb_drp_alloc *zones; __le16 current_bmp; DECLARE_BITMAP(tmp_bmp, UWB_NUM_MAS); DECLARE_BITMAP(tmp_mas_bm, UWB_MAS_PER_ZONE); zones = drp_ie->allocs; bitmap_copy(tmp_bmp, mas->bm, UWB_NUM_MAS); /* Determine unique MAS bitmaps in zones from bitmap. */ for (z = 0; z < UWB_NUM_ZONES; z++) { bitmap_copy(tmp_mas_bm, tmp_bmp, UWB_MAS_PER_ZONE); if (bitmap_weight(tmp_mas_bm, UWB_MAS_PER_ZONE) > 0) { bool found = false; current_bmp = (__le16) *tmp_mas_bm; for (i = 0; i < next; i++) { if (current_bmp == zones[i].mas_bm) { zones[i].zone_bm |= 1 << z; found = true; break; } } if (!found) { num_fields++; zones[next].zone_bm = 1 << z; zones[next].mas_bm = current_bmp; next++; } } bitmap_shift_right(tmp_bmp, tmp_bmp, UWB_MAS_PER_ZONE, UWB_NUM_MAS); } /* Store in format ready for transmission (le16). */ for (i = 0; i < num_fields; i++) { drp_ie->allocs[i].zone_bm = cpu_to_le16(zones[i].zone_bm); drp_ie->allocs[i].mas_bm = cpu_to_le16(zones[i].mas_bm); } drp_ie->hdr.length = sizeof(struct uwb_ie_drp) - sizeof(struct uwb_ie_hdr) + num_fields * sizeof(struct uwb_drp_alloc); }
int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx, struct pblk_rec_ctx *recovery, u64 *comp_bits, unsigned int comp) { struct nvm_tgt_dev *dev = pblk->dev; int max_secs = nvm_max_phys_sects(dev); struct nvm_rq *rec_rqd; struct pblk_c_ctx *rec_ctx; int nr_entries = c_ctx->nr_valid + c_ctx->nr_padded; rec_rqd = pblk_alloc_rqd(pblk, WRITE); if (IS_ERR(rec_rqd)) { pr_err("pblk: could not create recovery req.\n"); return -ENOMEM; } rec_ctx = nvm_rq_to_pdu(rec_rqd); /* Copy completion bitmap, but exclude the first X completed entries */ bitmap_shift_right((unsigned long int *)&rec_rqd->ppa_status, (unsigned long int *)comp_bits, comp, max_secs); /* Save the context for the entries that need to be re-written and * update current context with the completed entries. */ rec_ctx->sentry = pblk_rb_wrap_pos(&pblk->rwb, c_ctx->sentry + comp); if (comp >= c_ctx->nr_valid) { rec_ctx->nr_valid = 0; rec_ctx->nr_padded = nr_entries - comp; c_ctx->nr_padded = comp - c_ctx->nr_valid; } else { rec_ctx->nr_valid = c_ctx->nr_valid - comp; rec_ctx->nr_padded = c_ctx->nr_padded; c_ctx->nr_valid = comp; c_ctx->nr_padded = 0; } recovery->rqd = rec_rqd; recovery->pblk = pblk; return 0; }