Skip to content

Commit

Permalink
drivers: rkflash: Using kmap_atomic to build page address mapping
Browse files Browse the repository at this point in the history
The virtual address of allocated __GFP_HIGHMEM pages is not mapped,
Using kmap_atomic to build it, or it will failed like:

    Unable to handle kernel NULL pointer dereference at virtual address 00000000
    pgd = 50ec00c8
    [00000000] *pgd=00000000
    Internal error: Oops: 817 [#1] PREEMPT SMP ARM
    Modules linked in:
    CPU: 3 PID: 67 Comm: rkflash Not tainted 4.19.111 #67
    Hardware name: Generic DT based system
    PC is at memcpy+0x50/0x330
    LR is at 0x61640a68

Change-Id: I0cde9012d29e49d9ba751cb019ccfa784c01b7c7
Signed-off-by: Jon Lin <[email protected]>
  • Loading branch information
Jon Lin authored and rkhuangtao committed Oct 13, 2022
1 parent 0e1556a commit 70680c7
Showing 1 changed file with 35 additions and 32 deletions.
67 changes: 35 additions & 32 deletions drivers/rkflash/rkflash_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,26 @@ static int rkflash_blk_xfer(struct flash_blk_dev *dev,
static int rkflash_blk_check_buffer_align(struct request *req, char **pbuf)
{
int nr_vec = 0;
struct bio_vec bvec;
struct bio_vec bv;
struct req_iterator iter;
char *buffer;
void *firstbuf = 0;
char *nextbuffer = 0;

rq_for_each_segment(bvec, req, iter) {
buffer = page_address(bvec.bv_page) + bvec.bv_offset;
rq_for_each_segment(bv, req, iter) {
/* high mem return 0 and using kernel buffer */
if (PageHighMem(bv.bv_page))
return 0;

buffer = page_address(bv.bv_page) + bv.bv_offset;
if (!buffer)
return 0;
if (!firstbuf)
firstbuf = buffer;
nr_vec++;
if (nextbuffer && nextbuffer != buffer)
return 0;
nextbuffer = buffer + bvec.bv_len;
nextbuffer = buffer + bv.bv_len;
}
*pbuf = firstbuf;
return 1;
Expand All @@ -247,12 +253,11 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr,
struct request *req)
{
unsigned long block, nsect;
char *buf = NULL;
char *buf = NULL, *page_buf;
struct req_iterator rq_iter;
struct bio_vec bvec;
int ret;
unsigned long totle_nsect;
unsigned long rq_len = 0;

block = blk_rq_pos(req);
nsect = blk_rq_cur_bytes(req) >> 9;
Expand Down Expand Up @@ -281,11 +286,13 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr,
char *p = buf;

rq_for_each_segment(bvec, req, rq_iter) {
memcpy(page_address(bvec.bv_page) +
bvec.bv_offset,
p,
bvec.bv_len);
page_buf = kmap_atomic(bvec.bv_page);
memcpy(page_buf +
bvec.bv_offset,
p,
bvec.bv_len);
p += bvec.bv_len;
kunmap_atomic(page_buf);
}
}

Expand All @@ -296,30 +303,26 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr,
case REQ_OP_WRITE:
rkflash_print_bio("%s write block=%lx nsec=%lx\n", __func__, block, totle_nsect);

rq_for_each_segment(bvec, req, rq_iter) {
if ((page_address(bvec.bv_page) + bvec.bv_offset) == (buf + rq_len)) {
rq_len += bvec.bv_len;
} else {
if (rq_len) {
ret = rkflash_blk_xfer(dev,
block,
rq_len >> 9,
buf,
REQ_OP_WRITE);
}
block += rq_len >> 9;
buf = (page_address(bvec.bv_page) + bvec.bv_offset);
rq_len = bvec.bv_len;
}
}
buf = mtd_read_temp_buffer;
rkflash_blk_check_buffer_align(req, &buf);
if (buf == mtd_read_temp_buffer) {
char *p = buf;

if (rq_len) {
ret = rkflash_blk_xfer(dev,
block,
rq_len >> 9,
buf,
REQ_OP_WRITE);
rq_for_each_segment(bvec, req, rq_iter) {
page_buf = kmap_atomic(bvec.bv_page);
memcpy(p,
page_buf +
bvec.bv_offset,
bvec.bv_len);
p += bvec.bv_len;
kunmap_atomic(page_buf);
}
}
ret = rkflash_blk_xfer(dev,
block,
totle_nsect,
buf,
REQ_OP_WRITE);

if (ret)
return BLK_STS_IOERR;
Expand Down

0 comments on commit 70680c7

Please sign in to comment.