sfc: Cope with permissions enforcement added to firmware for SR-IOV
authorEdward Cree <ecree@solarflare.com>
Tue, 5 May 2015 23:59:18 +0000 (00:59 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 9 May 2015 20:16:48 +0000 (16:16 -0400)
* Accept EPERM in some simple cases, the following cases are handled:
1) efx_mcdi_read_assertion()
Unprivileged PCI functions aren't allowed to GET_ASSERTS.
We return success as it's up to the primary PF to deal with asserts.
2) efx_mcdi_mon_probe() in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to read sensor info, and
worrying about sensor data is the primary PF's job.
3) phy_op->reconfigure() in efx_init_port() and efx_reset_up()
Unprivileged functions aren't allowed to MC_CMD_SET_LINK, they just have
to accept the settings (including flow-control, which is what
efx_init_port() is worried about) they've been given.
4) Fallback to GET_WORKAROUNDS in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to set workarounds. So if
efx_mcdi_set_workaround() fails EPERM, use efx_mcdi_get_workarounds()
to find out if workaround_35388 is enabled.
5) If DRV_ATTACH gets EPERM, try without specifying fw-variant
Unprivileged PCI functions have to use a FIRMWARE_ID of 0xffffffff
(MC_CMD_FW_DONT_CARE).
6) Don't try to exit_assertion unless one had fired
Previously we called efx_mcdi_exit_assertion even if
efx_mcdi_read_assertion had received MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS.
This is unnecessary, and the resulting MC_CMD_REBOOT, even if the
AFTER_ASSERTION flag made it a no-op, would fail EPERM for unprivileged
PCI functions.
So make efx_mcdi_read_assertion return whether an assert happened, and only
call efx_mcdi_exit_assertion if it has.

Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/mcdi_pcol.h

index 0dff812..ae0ed2a 100644 (file)
@@ -286,10 +286,22 @@ static int efx_ef10_probe(struct efx_nic *efx)
                goto fail3;
        efx->timer_quantum_ns = 1536000 / rc; /* 1536 cycles */
 
-       /* Check whether firmware supports bug 35388 workaround */
+       /* Check whether firmware supports bug 35388 workaround.
+        * First try to enable it, then if we get EPERM, just
+        * ask if it's already enabled
+        */
        rc = efx_mcdi_set_workaround(efx, MC_CMD_WORKAROUND_BUG35388, true);
        if (rc == 0)
                nic_data->workaround_35388 = true;
+       else if (rc == -EPERM) {
+               unsigned int enabled;
+
+               rc = efx_mcdi_get_workarounds(efx, NULL, &enabled);
+               if (rc)
+                       goto fail3;
+               nic_data->workaround_35388 = enabled &
+                       MC_CMD_GET_WORKAROUNDS_OUT_BUG35388;
+       }
        else if (rc != -ENOSYS && rc != -ENOENT)
                goto fail3;
        netif_dbg(efx, probe, efx->net_dev,
@@ -297,7 +309,7 @@ static int efx_ef10_probe(struct efx_nic *efx)
                  nic_data->workaround_35388 ? "en" : "dis");
 
        rc = efx_mcdi_mon_probe(efx);
-       if (rc)
+       if (rc && rc != -EPERM)
                goto fail3;
 
        efx_ptp_probe(efx, NULL);
Simple merge
Simple merge
Simple merge
Simple merge