Anton Oshchepko
Anton Oshchepko

Reputation: 65

How correctly read/write from/to mtdblock into linux kernel space?

I am have code:

static unsigned char buffer[512];
static struct mtd_info *mtd_ptr = NULL;
static unsigned int *counter = NULL;

static void mtdblock_read(void)
{
  int readed = 0;
  int ret = 0;
  const unsigned int mtd_device_num = 12;
  counter = (unsigned int *)buffer;
  mtd_ptr = get_mtd_device(NULL, mtd_device_num);
  if(IS_ERR(mtd_ptr)){
    printk("Can't get mtd partition...");
    mtd_ptr = NULL;
    return;
  }
  printk("Found partition '%s'\n", mtd_ptr->name);
  if(mtd_ptr->read)
  {
    ret = mtd_ptr->read(mtd_ptr, 0, sizeof(buffer), &readed, buffer);
    printk("%s:%d - %d, readed: %d\n", __func__, __LINE__, ret, readed);
  }
  else
    printk("Not have 'read' ops\n");
  printk("current counter = 0x%08X\n", *counter);
}

static void mtdblock_write(void)
{
  int writed = 0;
  int ret = 0;
  (*counter) = 111;
  printk("Write counter (%d) to mtd\n", *counter);
  if(mtd_ptr && mtd_ptr->write)
  {
    ret = mtd_ptr->write(mtd_ptr, 0, sizeof(buffer), &writed, buffer);
    printk("%s:%d - %d, writed: %d\n", __func__, __LINE__, ret, writed);
    if(mtd_ptr->sync)
      mtd_ptr->sync(mtd_ptr);
  }
  else
    printk("Not have 'write' ops or mtd is not available\n");
}

void test()
{
  mtdblock_read();
  mtdblock_write();
  mtdblock_read();
}

mtdblock_read must read 512 bytes from mtdblock and display int value placed into first 4 bytes of buffer.

mtdblock_write puts 4-byte value at start of 512-byte buffer and write it to mtdblock.

test() executes test sequence:

  1. 1st mtdblock_read() - for read current value from mtdblock.

  2. mtdblock_write() - for write new value

  3. 2nd mtdblock_read() - for re-read writed value.

Problem in mtdblock_read (as my opinion) because I have trace output:

Found 13 partition 'dying_gasp'
mtdblock_read:303 - 0, readed: 512
current counter = 0x00000000
Write counter (1953719668) to mtd
mtdblock_write:322 - 0, writed: 512
Found 13 partition 'dying_gasp'
mtdblock_read:303 - 0, readed: 512
current counter = 0x00000000

From this I can see that mtd_ptr->read() have return value -74, but reports into readed that it have 512 bytes readed from mtdblock. But really it is not read data from mtdblock. Additionally I am check mtd_ptr->write() but it correctly report 512 bytes writed and have zero return value.

Can you help me for solve this problem? It is internal mtdblock driver error or I am skip major operations at read or write from/to mtdlock?

Upvotes: 0

Views: 1716

Answers (1)

Clifford Holden
Clifford Holden

Reputation: 16

This is a little late for the person asking the question, but perhaps someone else can benefit.

Found out that you cannot read into a buffer declared static if your mtd device is backed by the SPI driver. There is a section of code in spi_map_buf() in spi.c that checks for this:

if (vmalloced_buf || kmap_buf) {
        desc_len = min_t(int, max_seg_size, PAGE_SIZE);
        sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
    } else if (virt_addr_valid(buf)) {
        desc_len = min_t(int, max_seg_size, ctlr->max_dma_len);
        sgs = DIV_ROUND_UP(len, desc_len);
    } else {
        dev_err(&ctlr->dev,"Not vmalloced, not kmap, va not valid\n");
        return -EINVAL;
    }

So, if you go ahead and kmalloc the buffer, everything goes fine. Found this while trying to create a kernel mod that uses the MTD SPI SRAM on the i.MX6UL chip, and calling mtd_read directly.

Upvotes: 0

Related Questions