diff options
Diffstat (limited to 'drivers/lightnvm/pblk.h')
| -rw-r--r-- | drivers/lightnvm/pblk.h | 221 | 
1 files changed, 75 insertions, 146 deletions
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h index 4760af7b6499..02bb2e98f8a9 100644 --- a/drivers/lightnvm/pblk.h +++ b/drivers/lightnvm/pblk.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  /*   * Copyright (C) 2015 IT University of Copenhagen (rrpc.h)   * Copyright (C) 2016 CNEX Labs @@ -37,8 +38,6 @@  #define PBLK_SECTOR (512)  #define PBLK_EXPOSED_PAGE_SIZE (4096) -#define PBLK_MAX_REQ_ADDRS (64) -#define PBLK_MAX_REQ_ADDRS_PW (6)  #define PBLK_NR_CLOSE_JOBS (4) @@ -81,6 +80,12 @@ enum {  	PBLK_BLK_ST_CLOSED =	0x2,  }; +enum { +	PBLK_CHUNK_RESET_START, +	PBLK_CHUNK_RESET_DONE, +	PBLK_CHUNK_RESET_FAILED, +}; +  struct pblk_sec_meta {  	u64 reserved;  	__le64 lba; @@ -99,8 +104,8 @@ enum {  	PBLK_RL_LOW = 4  }; -#define pblk_dma_meta_size (sizeof(struct pblk_sec_meta) * PBLK_MAX_REQ_ADDRS) -#define pblk_dma_ppa_size (sizeof(u64) * PBLK_MAX_REQ_ADDRS) +#define pblk_dma_meta_size (sizeof(struct pblk_sec_meta) * NVM_MAX_VLBA) +#define pblk_dma_ppa_size (sizeof(u64) * NVM_MAX_VLBA)  /* write buffer completion context */  struct pblk_c_ctx { @@ -198,6 +203,11 @@ struct pblk_rb {  					 * will be 4KB  					 */ +	unsigned int back_thres;	/* Threshold that shall be maintained by +					 * the backpointer in order to respect +					 * geo->mw_cunits on a per chunk basis +					 */ +  	struct list_head pages;		/* List of data pages */  	spinlock_t w_lock;		/* Write lock */ @@ -218,8 +228,8 @@ struct pblk_lun {  struct pblk_gc_rq {  	struct pblk_line *line;  	void *data; -	u64 paddr_list[PBLK_MAX_REQ_ADDRS]; -	u64 lba_list[PBLK_MAX_REQ_ADDRS]; +	u64 paddr_list[NVM_MAX_VLBA]; +	u64 lba_list[NVM_MAX_VLBA];  	int nr_secs;  	int secs_to_gc;  	struct list_head list; @@ -532,6 +542,10 @@ struct pblk_line_mgmt {  	struct pblk_emeta *eline_meta[PBLK_DATA_LINES];  	unsigned long meta_bitmap; +	/* Cache and mempool for map/invalid bitmaps */ +	struct kmem_cache *bitmap_cache; +	mempool_t *bitmap_pool; +  	/* Helpers for fast bitmap calculations */  	unsigned long *bb_template;  	unsigned long *bb_aux; @@ -725,10 +739,8 @@ struct pblk_line_ws {  /*   * pblk ring buffer operations   */ -int pblk_rb_init(struct pblk_rb *rb, struct pblk_rb_entry *rb_entry_base, -		 unsigned int power_size, unsigned int power_seg_sz); -unsigned int pblk_rb_calculate_size(unsigned int nr_entries); -void *pblk_rb_entries_ref(struct pblk_rb *rb); +int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int threshold, +		 unsigned int seg_sz);  int pblk_rb_may_write_user(struct pblk_rb *rb, struct bio *bio,  			   unsigned int nr_entries, unsigned int *pos);  int pblk_rb_may_write_gc(struct pblk_rb *rb, unsigned int nr_entries, @@ -751,8 +763,8 @@ unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries);  unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);  unsigned int pblk_rb_sync_advance(struct pblk_rb *rb, unsigned int nr_entries); -struct pblk_rb_entry *pblk_rb_sync_scan_entry(struct pblk_rb *rb, -					      struct ppa_addr *ppa); +unsigned int pblk_rb_ptr_wrap(struct pblk_rb *rb, unsigned int p, +			      unsigned int nr_entries);  void pblk_rb_sync_end(struct pblk_rb *rb, unsigned long *flags);  unsigned int pblk_rb_flush_point_count(struct pblk_rb *rb); @@ -762,7 +774,7 @@ unsigned int pblk_rb_wrap_pos(struct pblk_rb *rb, unsigned int pos);  int pblk_rb_tear_down_check(struct pblk_rb *rb);  int pblk_rb_pos_oob(struct pblk_rb *rb, u64 pos); -void pblk_rb_data_free(struct pblk_rb *rb); +void pblk_rb_free(struct pblk_rb *rb);  ssize_t pblk_rb_sysfs(struct pblk_rb *rb, char *buf);  /* @@ -770,11 +782,13 @@ ssize_t pblk_rb_sysfs(struct pblk_rb *rb, char *buf);   */  struct nvm_rq *pblk_alloc_rqd(struct pblk *pblk, int type);  void pblk_free_rqd(struct pblk *pblk, struct nvm_rq *rqd, int type); +int pblk_alloc_rqd_meta(struct pblk *pblk, struct nvm_rq *rqd); +void pblk_free_rqd_meta(struct pblk *pblk, struct nvm_rq *rqd);  void pblk_set_sec_per_write(struct pblk *pblk, int sec_per_write);  int pblk_setup_w_rec_rq(struct pblk *pblk, struct nvm_rq *rqd,  			struct pblk_c_ctx *c_ctx);  void pblk_discard(struct pblk *pblk, struct bio *bio); -struct nvm_chk_meta *pblk_chunk_get_info(struct pblk *pblk); +struct nvm_chk_meta *pblk_get_chunk_meta(struct pblk *pblk);  struct nvm_chk_meta *pblk_chunk_get_off(struct pblk *pblk,  					      struct nvm_chk_meta *lp,  					      struct ppa_addr ppa); @@ -782,13 +796,17 @@ void pblk_log_write_err(struct pblk *pblk, struct nvm_rq *rqd);  void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd);  int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd);  int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd); +int pblk_submit_io_sync_sem(struct pblk *pblk, struct nvm_rq *rqd);  int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line); +void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd);  struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data,  			      unsigned int nr_secs, unsigned int len,  			      int alloc_type, gfp_t gfp_mask);  struct pblk_line *pblk_line_get(struct pblk *pblk);  struct pblk_line *pblk_line_get_first_data(struct pblk *pblk);  struct pblk_line *pblk_line_replace_data(struct pblk *pblk); +void pblk_ppa_to_line_put(struct pblk *pblk, struct ppa_addr ppa); +void pblk_rq_to_line_put(struct pblk *pblk, struct nvm_rq *rqd);  int pblk_line_recov_alloc(struct pblk *pblk, struct pblk_line *line);  void pblk_line_recov_close(struct pblk *pblk, struct pblk_line *line);  struct pblk_line *pblk_line_get_data(struct pblk *pblk); @@ -806,8 +824,8 @@ void pblk_gen_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,  		     void (*work)(struct work_struct *), gfp_t gfp_mask,  		     struct workqueue_struct *wq);  u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line); -int pblk_line_read_smeta(struct pblk *pblk, struct pblk_line *line); -int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line, +int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line); +int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line,  			 void *emeta_buf);  int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr erase_ppa);  void pblk_line_put(struct kref *ref); @@ -819,12 +837,11 @@ u64 pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);  u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);  int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail,  		   unsigned long secs_to_flush); -void pblk_up_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas); -void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, +void pblk_down_rq(struct pblk *pblk, struct ppa_addr ppa,  		  unsigned long *lun_bitmap); -void pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas); -void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, -		unsigned long *lun_bitmap); +void pblk_down_chunk(struct pblk *pblk, struct ppa_addr ppa); +void pblk_up_chunk(struct pblk *pblk, struct ppa_addr ppa); +void pblk_up_rq(struct pblk *pblk, unsigned long *lun_bitmap);  int pblk_bio_add_pages(struct pblk *pblk, struct bio *bio, gfp_t flags,  		       int nr_pages);  void pblk_bio_free_pages(struct pblk *pblk, struct bio *bio, int off, @@ -976,17 +993,15 @@ static inline int pblk_line_vsc(struct pblk_line *line)  	return le32_to_cpu(*line->vsc);  } -static inline int pblk_pad_distance(struct pblk *pblk) +static inline int pblk_ppa_to_line_id(struct ppa_addr p)  { -	struct nvm_tgt_dev *dev = pblk->dev; -	struct nvm_geo *geo = &dev->geo; - -	return geo->mw_cunits * geo->all_luns * geo->ws_opt; +	return p.a.blk;  } -static inline int pblk_ppa_to_line(struct ppa_addr p) +static inline struct pblk_line *pblk_ppa_to_line(struct pblk *pblk, +						 struct ppa_addr p)  { -	return p.a.blk; +	return &pblk->lines[pblk_ppa_to_line_id(p)];  }  static inline int pblk_ppa_to_pos(struct nvm_geo *geo, struct ppa_addr p) @@ -1034,6 +1049,25 @@ static inline struct ppa_addr addr_to_gen_ppa(struct pblk *pblk, u64 paddr,  	return ppa;  } +static inline struct nvm_chk_meta *pblk_dev_ppa_to_chunk(struct pblk *pblk, +							struct ppa_addr p) +{ +	struct nvm_tgt_dev *dev = pblk->dev; +	struct nvm_geo *geo = &dev->geo; +	struct pblk_line *line = pblk_ppa_to_line(pblk, p); +	int pos = pblk_ppa_to_pos(geo, p); + +	return &line->chks[pos]; +} + +static inline u64 pblk_dev_ppa_to_chunk_addr(struct pblk *pblk, +							struct ppa_addr p) +{ +	struct nvm_tgt_dev *dev = pblk->dev; + +	return dev_to_chunk_addr(dev->parent, &pblk->addrf, p); +} +  static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,  							struct ppa_addr p)  { @@ -1067,86 +1101,16 @@ static inline u64 pblk_dev_ppa_to_line_addr(struct pblk *pblk,  static inline struct ppa_addr pblk_ppa32_to_ppa64(struct pblk *pblk, u32 ppa32)  { -	struct ppa_addr ppa64; - -	ppa64.ppa = 0; - -	if (ppa32 == -1) { -		ppa64.ppa = ADDR_EMPTY; -	} else if (ppa32 & (1U << 31)) { -		ppa64.c.line = ppa32 & ((~0U) >> 1); -		ppa64.c.is_cached = 1; -	} else { -		struct nvm_tgt_dev *dev = pblk->dev; -		struct nvm_geo *geo = &dev->geo; - -		if (geo->version == NVM_OCSSD_SPEC_12) { -			struct nvm_addrf_12 *ppaf = -					(struct nvm_addrf_12 *)&pblk->addrf; - -			ppa64.g.ch = (ppa32 & ppaf->ch_mask) >> -							ppaf->ch_offset; -			ppa64.g.lun = (ppa32 & ppaf->lun_mask) >> -							ppaf->lun_offset; -			ppa64.g.blk = (ppa32 & ppaf->blk_mask) >> -							ppaf->blk_offset; -			ppa64.g.pg = (ppa32 & ppaf->pg_mask) >> -							ppaf->pg_offset; -			ppa64.g.pl = (ppa32 & ppaf->pln_mask) >> -							ppaf->pln_offset; -			ppa64.g.sec = (ppa32 & ppaf->sec_mask) >> -							ppaf->sec_offset; -		} else { -			struct nvm_addrf *lbaf = &pblk->addrf; - -			ppa64.m.grp = (ppa32 & lbaf->ch_mask) >> -							lbaf->ch_offset; -			ppa64.m.pu = (ppa32 & lbaf->lun_mask) >> -							lbaf->lun_offset; -			ppa64.m.chk = (ppa32 & lbaf->chk_mask) >> -							lbaf->chk_offset; -			ppa64.m.sec = (ppa32 & lbaf->sec_mask) >> -							lbaf->sec_offset; -		} -	} +	struct nvm_tgt_dev *dev = pblk->dev; -	return ppa64; +	return nvm_ppa32_to_ppa64(dev->parent, &pblk->addrf, ppa32);  }  static inline u32 pblk_ppa64_to_ppa32(struct pblk *pblk, struct ppa_addr ppa64)  { -	u32 ppa32 = 0; - -	if (ppa64.ppa == ADDR_EMPTY) { -		ppa32 = ~0U; -	} else if (ppa64.c.is_cached) { -		ppa32 |= ppa64.c.line; -		ppa32 |= 1U << 31; -	} else { -		struct nvm_tgt_dev *dev = pblk->dev; -		struct nvm_geo *geo = &dev->geo; - -		if (geo->version == NVM_OCSSD_SPEC_12) { -			struct nvm_addrf_12 *ppaf = -					(struct nvm_addrf_12 *)&pblk->addrf; - -			ppa32 |= ppa64.g.ch << ppaf->ch_offset; -			ppa32 |= ppa64.g.lun << ppaf->lun_offset; -			ppa32 |= ppa64.g.blk << ppaf->blk_offset; -			ppa32 |= ppa64.g.pg << ppaf->pg_offset; -			ppa32 |= ppa64.g.pl << ppaf->pln_offset; -			ppa32 |= ppa64.g.sec << ppaf->sec_offset; -		} else { -			struct nvm_addrf *lbaf = &pblk->addrf; - -			ppa32 |= ppa64.m.grp << lbaf->ch_offset; -			ppa32 |= ppa64.m.pu << lbaf->lun_offset; -			ppa32 |= ppa64.m.chk << lbaf->chk_offset; -			ppa32 |= ppa64.m.sec << lbaf->sec_offset; -		} -	} +	struct nvm_tgt_dev *dev = pblk->dev; -	return ppa32; +	return nvm_ppa64_to_ppa32(dev->parent, &pblk->addrf, ppa64);  }  static inline struct ppa_addr pblk_trans_map_get(struct pblk *pblk, @@ -1255,44 +1219,6 @@ static inline u32 pblk_calc_emeta_crc(struct pblk *pblk,  	return crc;  } -static inline int pblk_set_progr_mode(struct pblk *pblk, int type) -{ -	struct nvm_tgt_dev *dev = pblk->dev; -	struct nvm_geo *geo = &dev->geo; -	int flags; - -	if (geo->version == NVM_OCSSD_SPEC_20) -		return 0; - -	flags = geo->pln_mode >> 1; - -	if (type == PBLK_WRITE) -		flags |= NVM_IO_SCRAMBLE_ENABLE; - -	return flags; -} - -enum { -	PBLK_READ_RANDOM	= 0, -	PBLK_READ_SEQUENTIAL	= 1, -}; - -static inline int pblk_set_read_mode(struct pblk *pblk, int type) -{ -	struct nvm_tgt_dev *dev = pblk->dev; -	struct nvm_geo *geo = &dev->geo; -	int flags; - -	if (geo->version == NVM_OCSSD_SPEC_20) -		return 0; - -	flags = NVM_IO_SUSPEND | NVM_IO_SCRAMBLE_ENABLE; -	if (type == PBLK_READ_SEQUENTIAL) -		flags |= geo->pln_mode >> 1; - -	return flags; -} -  static inline int pblk_io_aligned(struct pblk *pblk, int nr_secs)  {  	return !(nr_secs % pblk->min_write_pgs); @@ -1375,9 +1301,7 @@ static inline int pblk_boundary_ppa_checks(struct nvm_tgt_dev *tgt_dev,  static inline int pblk_check_io(struct pblk *pblk, struct nvm_rq *rqd)  {  	struct nvm_tgt_dev *dev = pblk->dev; -	struct ppa_addr *ppa_list; - -	ppa_list = (rqd->nr_ppas > 1) ? rqd->ppa_list : &rqd->ppa_addr; +	struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd);  	if (pblk_boundary_ppa_checks(dev, ppa_list, rqd->nr_ppas)) {  		WARN_ON(1); @@ -1386,12 +1310,10 @@ static inline int pblk_check_io(struct pblk *pblk, struct nvm_rq *rqd)  	if (rqd->opcode == NVM_OP_PWRITE) {  		struct pblk_line *line; -		struct ppa_addr ppa;  		int i;  		for (i = 0; i < rqd->nr_ppas; i++) { -			ppa = ppa_list[i]; -			line = &pblk->lines[pblk_ppa_to_line(ppa)]; +			line = pblk_ppa_to_line(pblk, ppa_list[i]);  			spin_lock(&line->lock);  			if (line->state != PBLK_LINESTATE_OPEN) { @@ -1441,4 +1363,11 @@ static inline void pblk_setup_uuid(struct pblk *pblk)  	uuid_le_gen(&uuid);  	memcpy(pblk->instance_uuid, uuid.b, 16);  } + +static inline char *pblk_disk_name(struct pblk *pblk) +{ +	struct gendisk *disk = pblk->disk; + +	return disk->disk_name; +}  #endif /* PBLK_H_ */  | 
