module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
 
-static char fw_type[LIO_MAX_FW_TYPE_LEN] = LIO_FW_NAME_TYPE_NIC;
+static char fw_type[LIO_MAX_FW_TYPE_LEN] = LIO_FW_NAME_TYPE_AUTO;
 module_param_string(fw_type, fw_type, sizeof(fw_type), 0444);
-MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded. Default \"nic\".  Use \"none\" to load firmware from flash.");
+MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded (default is \"auto\"), which uses firmware in flash, if present, else loads \"nic\".");
 
 static u32 console_bitmask;
 module_param(console_bitmask, int, 0644);
        return 0;
 }
 
-static bool fw_type_is_none(void)
+static bool fw_type_is_auto(void)
 {
-       return strncmp(fw_type, LIO_FW_NAME_TYPE_NONE,
-                      sizeof(LIO_FW_NAME_TYPE_NONE)) == 0;
+       return strncmp(fw_type, LIO_FW_NAME_TYPE_AUTO,
+                      sizeof(LIO_FW_NAME_TYPE_AUTO)) == 0;
 }
 
 /**
                 * Implementation note: only soft-reset the device
                 * if it is a CN6XXX OR the LAST CN23XX device.
                 */
-               if (fw_type_is_none())
+               if (atomic_read(oct->adapter_fw_state) == FW_IS_PRELOADED)
                        octeon_pci_flr(oct);
                else if (OCTEON_CN6XXX(oct) || !refcount)
                        oct->fn_list.soft_reset(oct);
        char fw_name[LIO_MAX_FW_FILENAME_LEN];
        char *tmp_fw_type;
 
-       if (fw_type[0] == '\0')
+       if (fw_type_is_auto())
                tmp_fw_type = LIO_FW_NAME_TYPE_NIC;
        else
                tmp_fw_type = fw_type;
 static int octeon_device_init(struct octeon_device *octeon_dev)
 {
        int j, ret;
-       int fw_loaded = 0;
        char bootcmd[] = "\n";
        char *dbg_enb = NULL;
+       enum lio_fw_state fw_state;
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)octeon_dev->priv;
        atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
 
        octeon_dev->app_mode = CVM_DRV_INVALID_APP;
 
-       if (OCTEON_CN23XX_PF(octeon_dev)) {
-               if (!cn23xx_fw_loaded(octeon_dev) && !fw_type_is_none()) {
-                       fw_loaded = 0;
-                       /* Do a soft reset of the Octeon device. */
-                       if (octeon_dev->fn_list.soft_reset(octeon_dev))
-                               return 1;
-                       /* things might have changed */
-                       if (!cn23xx_fw_loaded(octeon_dev))
-                               fw_loaded = 0;
-                       else
-                               fw_loaded = 1;
-               } else {
-                       fw_loaded = 1;
-               }
-       } else if (octeon_dev->fn_list.soft_reset(octeon_dev)) {
-               return 1;
+       /* CN23XX supports preloaded firmware if the following is true:
+        *
+        * The adapter indicates that firmware is currently running AND
+        * 'fw_type' is 'auto'.
+        *
+        * (default state is NEEDS_TO_BE_LOADED, override it if appropriate).
+        */
+       if (OCTEON_CN23XX_PF(octeon_dev) &&
+           cn23xx_fw_loaded(octeon_dev) && fw_type_is_auto()) {
+               atomic_cmpxchg(octeon_dev->adapter_fw_state,
+                              FW_NEEDS_TO_BE_LOADED, FW_IS_PRELOADED);
        }
 
+       /* If loading firmware, only first device of adapter needs to do so. */
+       fw_state = atomic_cmpxchg(octeon_dev->adapter_fw_state,
+                                 FW_NEEDS_TO_BE_LOADED,
+                                 FW_IS_BEING_LOADED);
+
+       /* Here, [local variable] 'fw_state' is set to one of:
+        *
+        *   FW_IS_PRELOADED:       No firmware is to be loaded (see above)
+        *   FW_NEEDS_TO_BE_LOADED: The driver's first instance will load
+        *                          firmware to the adapter.
+        *   FW_IS_BEING_LOADED:    The driver's second instance will not load
+        *                          firmware to the adapter.
+        */
+
+       /* Prior to f/w load, perform a soft reset of the Octeon device;
+        * if error resetting, return w/error.
+        */
+       if (fw_state == FW_NEEDS_TO_BE_LOADED)
+               if (octeon_dev->fn_list.soft_reset(octeon_dev))
+                       return 1;
+
        /* Initialize the dispatch mechanism used to push packets arriving on
         * Octeon Output queues.
         */
 
        atomic_set(&octeon_dev->status, OCT_DEV_IO_QUEUES_DONE);
 
-       if ((!OCTEON_CN23XX_PF(octeon_dev)) || !fw_loaded) {
+       if (fw_state == FW_NEEDS_TO_BE_LOADED) {
                dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
                if (!ddr_timeout) {
                        dev_info(&octeon_dev->pci_dev->dev,
                        dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
                        return 1;
                }
+
+               atomic_set(octeon_dev->adapter_fw_state, FW_HAS_BEEN_LOADED);
        }
 
        handshake[octeon_dev->octeon_id].init_ok = 1;
 
 
 static struct octeon_device *octeon_device[MAX_OCTEON_DEVICES];
 static atomic_t adapter_refcounts[MAX_OCTEON_DEVICES];
+static atomic_t adapter_fw_states[MAX_OCTEON_DEVICES];
 
 static u32 octeon_device_count;
 /* locks device array (i.e. octeon_device[]) */
        oct->adapter_refcount = &adapter_refcounts[oct->octeon_id];
        atomic_set(oct->adapter_refcount, 0);
 
+       /* Like the reference count, the f/w state is shared 'per-adapter' */
+       oct->adapter_fw_state = &adapter_fw_states[oct->octeon_id];
+       atomic_set(oct->adapter_fw_state, FW_NEEDS_TO_BE_LOADED);
+
        spin_lock(&octeon_devices_lock);
        for (idx = (int)oct->octeon_id - 1; idx >= 0; idx--) {
                if (!octeon_device[idx]) {
                        atomic_inc(oct->adapter_refcount);
                        return 1; /* here, refcount is guaranteed to be 1 */
                }
-               /* if another device is at same bus/dev, use its refcounter */
+               /* If another device is at same bus/dev, use its refcounter
+                * (and f/w state variable).
+                */
                if ((octeon_device[idx]->loc.bus == bus) &&
                    (octeon_device[idx]->loc.dev == dev)) {
                        oct->adapter_refcount =
                                octeon_device[idx]->adapter_refcount;
+                       oct->adapter_fw_state =
+                               octeon_device[idx]->adapter_fw_state;
                        break;
                }
        }