]> git.droids-corp.org - dpdk.git/commitdiff
net/sfc/base: precheck and verify flash writes
authorAndy Moreton <amoreton@solarflare.com>
Thu, 16 Nov 2017 08:04:00 +0000 (08:04 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
Read existing flash content before writing, so the flash write can be
avoided if the existing partition content matches the new image. This
avoids unnecessary write cycles for the flash device, and may also be
faster. If the flash does need to be updated, verify the content after
writing.

Note that reading the flash content after writing but before calling
efx_nvram-rw_finish() avoids firmware bug68170, which can lead to
signed image updates failing on Medford.

Signed-off-by: Andy Moreton <amoreton@solarflare.com>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
drivers/net/sfc/base/ef10_impl.h
drivers/net/sfc/base/ef10_nvram.c
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_impl.h
drivers/net/sfc/base/efx_nvram.c

index 46241131cfb805866225cb1f85e797336fb73770..97922f3e7785d4134a0ce15746ee5641ca06b14f 100644 (file)
@@ -442,6 +442,14 @@ ef10_nvram_partn_read(
        __out_bcount(size)      caddr_t data,
        __in                    size_t size);
 
+extern __checkReturn           efx_rc_t
+ef10_nvram_partn_read_backup(
+       __in                    efx_nic_t *enp,
+       __in                    uint32_t partn,
+       __in                    unsigned int offset,
+       __out_bcount(size)      caddr_t data,
+       __in                    size_t size);
+
 extern __checkReturn           efx_rc_t
 ef10_nvram_partn_erase(
        __in                    efx_nic_t *enp,
index a70838b77342154d9bc49cb4eaafa4fefa4bb91e..68f14d54d26f9eb845939c9fb47987b4cfe880e0 100644 (file)
@@ -1937,13 +1937,36 @@ ef10_nvram_partn_read(
        __in                    size_t size)
 {
        /*
-        * Read requests which come in through the EFX API expect to
-        * read the current, active partition.
+        * An A/B partition has two data stores (current and backup).
+        * Read requests which come in through the EFX API expect to read the
+        * current, active store of an A/B partition. For non A/B partitions,
+        * there is only a single store and so the mode param is ignored.
         */
        return ef10_nvram_partn_read_mode(enp, partn, offset, data, size,
                            MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT);
 }
 
+       __checkReturn           efx_rc_t
+ef10_nvram_partn_read_backup(
+       __in                    efx_nic_t *enp,
+       __in                    uint32_t partn,
+       __in                    unsigned int offset,
+       __out_bcount(size)      caddr_t data,
+       __in                    size_t size)
+{
+       /*
+        * An A/B partition has two data stores (current and backup).
+        * Read the backup store of an A/B partition (i.e. the store currently
+        * being written to if the partition is locked).
+        *
+        * This is needed when comparing the existing partition content to avoid
+        * unnecessary writes, or to read back what has been written to check
+        * that the writes have succeeded.
+        */
+       return ef10_nvram_partn_read_mode(enp, partn, offset, data, size,
+                           MC_CMD_NVRAM_READ_IN_V2_TARGET_BACKUP);
+}
+
        __checkReturn           efx_rc_t
 ef10_nvram_partn_erase(
        __in                    efx_nic_t *enp,
index b298a75af2383c6add6b3caf7cb49368d7af79fa..834eea0b67b0dbebe1fbe990fd6451062aca85b0 100644 (file)
@@ -1429,6 +1429,14 @@ efx_nvram_read_chunk(
        __out_bcount(size)      caddr_t data,
        __in                    size_t size);
 
+extern __checkReturn           efx_rc_t
+efx_nvram_read_backup(
+       __in                    efx_nic_t *enp,
+       __in                    efx_nvram_type_t type,
+       __in                    unsigned int offset,
+       __out_bcount(size)      caddr_t data,
+       __in                    size_t size);
+
 extern __checkReturn           efx_rc_t
 efx_nvram_set_version(
        __in                    efx_nic_t *enp,
index 7b07f3465dff9988137d22246799dea71aa93d22..2be8b9c4bb900a42bdb96c61fec22b4d592b2ca2 100644 (file)
@@ -475,6 +475,8 @@ typedef struct efx_nvram_ops_s {
        efx_rc_t        (*envo_partn_rw_start)(efx_nic_t *, uint32_t, size_t *);
        efx_rc_t        (*envo_partn_read)(efx_nic_t *, uint32_t,
                                            unsigned int, caddr_t, size_t);
+       efx_rc_t        (*envo_partn_read_backup)(efx_nic_t *, uint32_t,
+                                           unsigned int, caddr_t, size_t);
        efx_rc_t        (*envo_partn_erase)(efx_nic_t *, uint32_t,
                                            unsigned int, size_t);
        efx_rc_t        (*envo_partn_write)(efx_nic_t *, uint32_t,
index bdad5d509ac88d382f6f3f882c244c5af4576b58..affe496732b40e25528a3b1d362178d70aa249be 100644 (file)
@@ -43,6 +43,7 @@ static const efx_nvram_ops_t  __efx_nvram_siena_ops = {
        siena_nvram_partn_size,         /* envo_partn_size */
        siena_nvram_partn_rw_start,     /* envo_partn_rw_start */
        siena_nvram_partn_read,         /* envo_partn_read */
+       siena_nvram_partn_read,         /* envo_partn_read_backup */
        siena_nvram_partn_erase,        /* envo_partn_erase */
        siena_nvram_partn_write,        /* envo_partn_write */
        siena_nvram_partn_rw_finish,    /* envo_partn_rw_finish */
@@ -63,6 +64,7 @@ static const efx_nvram_ops_t  __efx_nvram_ef10_ops = {
        ef10_nvram_partn_size,          /* envo_partn_size */
        ef10_nvram_partn_rw_start,      /* envo_partn_rw_start */
        ef10_nvram_partn_read,          /* envo_partn_read */
+       ef10_nvram_partn_read_backup,   /* envo_partn_read_backup */
        ef10_nvram_partn_erase,         /* envo_partn_erase */
        ef10_nvram_partn_write,         /* envo_partn_write */
        ef10_nvram_partn_rw_finish,     /* envo_partn_rw_finish */
@@ -277,6 +279,48 @@ efx_nvram_read_chunk(
 
        return (0);
 
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Read from the backup (writeable) store of an A/B partition.
+ * For non A/B partitions, there is only a single store, and so this
+ * function has the same behaviour as efx_nvram_read_chunk().
+ */
+       __checkReturn           efx_rc_t
+efx_nvram_read_backup(
+       __in                    efx_nic_t *enp,
+       __in                    efx_nvram_type_t type,
+       __in                    unsigned int offset,
+       __out_bcount(size)      caddr_t data,
+       __in                    size_t size)
+{
+       const efx_nvram_ops_t *envop = enp->en_envop;
+       uint32_t partn;
+       efx_rc_t rc;
+
+       EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
+
+       EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
+       EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
+
+       if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
+               goto fail1;
+
+       EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
+
+       if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
+                   data, size)) != 0)
+               goto fail2;
+
+       return (0);
+
 fail2:
        EFSYS_PROBE(fail2);
 fail1: