diff options
Diffstat (limited to 'drivers/lightnvm/pblk-core.c')
| -rw-r--r-- | drivers/lightnvm/pblk-core.c | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index 08d166ac4f3c..0a41fb998d55 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c | |||
| @@ -1460,10 +1460,8 @@ void pblk_line_free(struct pblk *pblk, struct pblk_line *line) | |||
| 1460 | line->emeta = NULL; | 1460 | line->emeta = NULL; |
| 1461 | } | 1461 | } |
| 1462 | 1462 | ||
| 1463 | void pblk_line_put(struct kref *ref) | 1463 | static void __pblk_line_put(struct pblk *pblk, struct pblk_line *line) |
| 1464 | { | 1464 | { |
| 1465 | struct pblk_line *line = container_of(ref, struct pblk_line, ref); | ||
| 1466 | struct pblk *pblk = line->pblk; | ||
| 1467 | struct pblk_line_mgmt *l_mg = &pblk->l_mg; | 1465 | struct pblk_line_mgmt *l_mg = &pblk->l_mg; |
| 1468 | 1466 | ||
| 1469 | spin_lock(&line->lock); | 1467 | spin_lock(&line->lock); |
| @@ -1481,6 +1479,43 @@ void pblk_line_put(struct kref *ref) | |||
| 1481 | pblk_rl_free_lines_inc(&pblk->rl, line); | 1479 | pblk_rl_free_lines_inc(&pblk->rl, line); |
| 1482 | } | 1480 | } |
| 1483 | 1481 | ||
| 1482 | static void pblk_line_put_ws(struct work_struct *work) | ||
| 1483 | { | ||
| 1484 | struct pblk_line_ws *line_put_ws = container_of(work, | ||
| 1485 | struct pblk_line_ws, ws); | ||
| 1486 | struct pblk *pblk = line_put_ws->pblk; | ||
| 1487 | struct pblk_line *line = line_put_ws->line; | ||
| 1488 | |||
| 1489 | __pblk_line_put(pblk, line); | ||
| 1490 | mempool_free(line_put_ws, pblk->gen_ws_pool); | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | void pblk_line_put(struct kref *ref) | ||
| 1494 | { | ||
| 1495 | struct pblk_line *line = container_of(ref, struct pblk_line, ref); | ||
| 1496 | struct pblk *pblk = line->pblk; | ||
| 1497 | |||
| 1498 | __pblk_line_put(pblk, line); | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | void pblk_line_put_wq(struct kref *ref) | ||
| 1502 | { | ||
| 1503 | struct pblk_line *line = container_of(ref, struct pblk_line, ref); | ||
| 1504 | struct pblk *pblk = line->pblk; | ||
| 1505 | struct pblk_line_ws *line_put_ws; | ||
| 1506 | |||
| 1507 | line_put_ws = mempool_alloc(pblk->gen_ws_pool, GFP_ATOMIC); | ||
| 1508 | if (!line_put_ws) | ||
| 1509 | return; | ||
| 1510 | |||
| 1511 | line_put_ws->pblk = pblk; | ||
| 1512 | line_put_ws->line = line; | ||
| 1513 | line_put_ws->priv = NULL; | ||
| 1514 | |||
| 1515 | INIT_WORK(&line_put_ws->ws, pblk_line_put_ws); | ||
| 1516 | queue_work(pblk->r_end_wq, &line_put_ws->ws); | ||
| 1517 | } | ||
| 1518 | |||
| 1484 | int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa) | 1519 | int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa) |
| 1485 | { | 1520 | { |
| 1486 | struct nvm_rq *rqd; | 1521 | struct nvm_rq *rqd; |
| @@ -1878,8 +1913,19 @@ void pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas, | |||
| 1878 | int i; | 1913 | int i; |
| 1879 | 1914 | ||
| 1880 | spin_lock(&pblk->trans_lock); | 1915 | spin_lock(&pblk->trans_lock); |
| 1881 | for (i = 0; i < nr_secs; i++) | 1916 | for (i = 0; i < nr_secs; i++) { |
| 1882 | ppas[i] = pblk_trans_map_get(pblk, blba + i); | 1917 | struct ppa_addr ppa; |
| 1918 | |||
| 1919 | ppa = ppas[i] = pblk_trans_map_get(pblk, blba + i); | ||
| 1920 | |||
| 1921 | /* If the L2P entry maps to a line, the reference is valid */ | ||
| 1922 | if (!pblk_ppa_empty(ppa) && !pblk_addr_in_cache(ppa)) { | ||
| 1923 | int line_id = pblk_dev_ppa_to_line(ppa); | ||
| 1924 | struct pblk_line *line = &pblk->lines[line_id]; | ||
| 1925 | |||
| 1926 | kref_get(&line->ref); | ||
| 1927 | } | ||
| 1928 | } | ||
| 1883 | spin_unlock(&pblk->trans_lock); | 1929 | spin_unlock(&pblk->trans_lock); |
| 1884 | } | 1930 | } |
| 1885 | 1931 | ||
