ice_get_orom_civd_data(struct ice_hw *hw, enum ice_bank_select bank,
                       struct ice_orom_civd_info *civd)
 {
-       struct ice_orom_civd_info tmp;
+       u8 *orom_data;
        int status;
        u32 offset;
 
         * The first 4 bytes must contain the ASCII characters "$CIV".
         * A simple modulo 256 sum of all of the bytes of the structure must
         * equal 0.
+        *
+        * The exact location is unknown and varies between images but is
+        * usually somewhere in the middle of the bank. We need to scan the
+        * Option ROM bank to locate it.
+        *
+        * It's significantly faster to read the entire Option ROM up front
+        * using the maximum page size, than to read each possible location
+        * with a separate firmware command.
         */
+       orom_data = vzalloc(hw->flash.banks.orom_size);
+       if (!orom_data)
+               return -ENOMEM;
+
+       status = ice_read_flash_module(hw, bank, ICE_SR_1ST_OROM_BANK_PTR, 0,
+                                      orom_data, hw->flash.banks.orom_size);
+       if (status) {
+               ice_debug(hw, ICE_DBG_NVM, "Unable to read Option ROM data\n");
+               return status;
+       }
+
+       /* Scan the memory buffer to locate the CIVD data section */
        for (offset = 0; (offset + 512) <= hw->flash.banks.orom_size; offset += 512) {
+               struct ice_orom_civd_info *tmp;
                u8 sum = 0, i;
 
-               status = ice_read_flash_module(hw, bank, ICE_SR_1ST_OROM_BANK_PTR,
-                                              offset, (u8 *)&tmp, sizeof(tmp));
-               if (status) {
-                       ice_debug(hw, ICE_DBG_NVM, "Unable to read Option ROM CIVD data\n");
-                       return status;
-               }
+               tmp = (struct ice_orom_civd_info *)&orom_data[offset];
 
                /* Skip forward until we find a matching signature */
-               if (memcmp("$CIV", tmp.signature, sizeof(tmp.signature)) != 0)
+               if (memcmp("$CIV", tmp->signature, sizeof(tmp->signature)) != 0)
                        continue;
 
+               ice_debug(hw, ICE_DBG_NVM, "Found CIVD section at offset %u\n",
+                         offset);
+
                /* Verify that the simple checksum is zero */
-               for (i = 0; i < sizeof(tmp); i++)
+               for (i = 0; i < sizeof(*tmp); i++)
                        /* cppcheck-suppress objectIndex */
-                       sum += ((u8 *)&tmp)[i];
+                       sum += ((u8 *)tmp)[i];
 
                if (sum) {
                        ice_debug(hw, ICE_DBG_NVM, "Found CIVD data with invalid checksum of %u\n",
                                  sum);
-                       return -EIO;
+                       goto err_invalid_checksum;
                }
 
-               *civd = tmp;
+               *civd = *tmp;
+               vfree(orom_data);
                return 0;
        }
 
+       ice_debug(hw, ICE_DBG_NVM, "Unable to locate CIVD data within the Option ROM\n");
+
+err_invalid_checksum:
+       vfree(orom_data);
        return -EIO;
 }