Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[pandora-kernel.git] / drivers / net / sfc / falcon.c
index 1763b9a..61ddd2c 100644 (file)
@@ -24,7 +24,6 @@
 #include "nic.h"
 #include "regs.h"
 #include "io.h"
-#include "mdio_10g.h"
 #include "phy.h"
 #include "workarounds.h"
 
@@ -255,7 +254,6 @@ int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi,
        /* Input validation */
        if (len > FALCON_SPI_MAX_LEN)
                return -EINVAL;
-       BUG_ON(!mutex_is_locked(&efx->spi_lock));
 
        /* Check that previous command is not still running */
        rc = falcon_spi_poll(efx);
@@ -719,6 +717,7 @@ static int falcon_mdio_write(struct net_device *net_dev,
                             int prtad, int devad, u16 addr, u16 value)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
+       struct falcon_nic_data *nic_data = efx->nic_data;
        efx_oword_t reg;
        int rc;
 
@@ -726,7 +725,7 @@ static int falcon_mdio_write(struct net_device *net_dev,
                   "writing MDIO %d register %d.%d with 0x%04x\n",
                    prtad, devad, addr, value);
 
-       mutex_lock(&efx->mdio_lock);
+       mutex_lock(&nic_data->mdio_lock);
 
        /* Check MDIO not currently being accessed */
        rc = falcon_gmii_wait(efx);
@@ -762,7 +761,7 @@ static int falcon_mdio_write(struct net_device *net_dev,
        }
 
 out:
-       mutex_unlock(&efx->mdio_lock);
+       mutex_unlock(&nic_data->mdio_lock);
        return rc;
 }
 
@@ -771,10 +770,11 @@ static int falcon_mdio_read(struct net_device *net_dev,
                            int prtad, int devad, u16 addr)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
+       struct falcon_nic_data *nic_data = efx->nic_data;
        efx_oword_t reg;
        int rc;
 
-       mutex_lock(&efx->mdio_lock);
+       mutex_lock(&nic_data->mdio_lock);
 
        /* Check MDIO not currently being accessed */
        rc = falcon_gmii_wait(efx);
@@ -813,7 +813,7 @@ static int falcon_mdio_read(struct net_device *net_dev,
        }
 
 out:
-       mutex_unlock(&efx->mdio_lock);
+       mutex_unlock(&nic_data->mdio_lock);
        return rc;
 }
 
@@ -841,6 +841,7 @@ static int falcon_probe_port(struct efx_nic *efx)
        }
 
        /* Fill out MDIO structure and loopback modes */
+       mutex_init(&nic_data->mdio_lock);
        efx->mdio.mdio_read = falcon_mdio_read;
        efx->mdio.mdio_write = falcon_mdio_write;
        rc = efx->phy_op->probe(efx);
@@ -880,6 +881,41 @@ static void falcon_remove_port(struct efx_nic *efx)
        efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
+/* Global events are basically PHY events */
+static bool
+falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
+{
+       struct efx_nic *efx = channel->efx;
+       struct falcon_nic_data *nic_data = efx->nic_data;
+
+       if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
+           EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
+           EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR))
+               /* Ignored */
+               return true;
+
+       if ((efx_nic_rev(efx) == EFX_REV_FALCON_B0) &&
+           EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
+               nic_data->xmac_poll_required = true;
+               return true;
+       }
+
+       if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
+           EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
+           EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
+               netif_err(efx, rx_err, efx->net_dev,
+                         "channel %d seen global RX_RESET event. Resetting.\n",
+                         channel->channel);
+
+               atomic_inc(&efx->rx_reset);
+               efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
+                                  RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+               return true;
+       }
+
+       return false;
+}
+
 /**************************************************************************
  *
  * Falcon test code
@@ -889,6 +925,7 @@ static void falcon_remove_port(struct efx_nic *efx)
 static int
 falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
 {
+       struct falcon_nic_data *nic_data = efx->nic_data;
        struct falcon_nvconfig *nvconfig;
        struct efx_spi_device *spi;
        void *region;
@@ -896,8 +933,11 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
        __le16 *word, *limit;
        u32 csum;
 
-       spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
-       if (!spi)
+       if (efx_spi_present(&nic_data->spi_flash))
+               spi = &nic_data->spi_flash;
+       else if (efx_spi_present(&nic_data->spi_eeprom))
+               spi = &nic_data->spi_eeprom;
+       else
                return -EINVAL;
 
        region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
@@ -905,12 +945,13 @@ falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
                return -ENOMEM;
        nvconfig = region + FALCON_NVCONFIG_OFFSET;
 
-       mutex_lock(&efx->spi_lock);
+       mutex_lock(&nic_data->spi_lock);
        rc = falcon_spi_read(efx, spi, 0, FALCON_NVCONFIG_END, NULL, region);
-       mutex_unlock(&efx->spi_lock);
+       mutex_unlock(&nic_data->spi_lock);
        if (rc) {
                netif_err(efx, hw, efx->net_dev, "Failed to read %s\n",
-                         efx->spi_flash ? "flash" : "EEPROM");
+                         efx_spi_present(&nic_data->spi_flash) ?
+                         "flash" : "EEPROM");
                rc = -EIO;
                goto out;
        }
@@ -1012,7 +1053,7 @@ static int falcon_b0_test_registers(struct efx_nic *efx)
 
 /* Resets NIC to known state.  This routine must be called in process
  * context and is allowed to sleep. */
-static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
 {
        struct falcon_nic_data *nic_data = efx->nic_data;
        efx_oword_t glb_ctl_reg_ker;
@@ -1093,6 +1134,18 @@ fail3:
        return rc;
 }
 
+static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
+{
+       struct falcon_nic_data *nic_data = efx->nic_data;
+       int rc;
+
+       mutex_lock(&nic_data->spi_lock);
+       rc = __falcon_reset_hw(efx, method);
+       mutex_unlock(&nic_data->spi_lock);
+
+       return rc;
+}
+
 static void falcon_monitor(struct efx_nic *efx)
 {
        bool link_changed;
@@ -1174,16 +1227,11 @@ static int falcon_reset_sram(struct efx_nic *efx)
        return -ETIMEDOUT;
 }
 
-static int falcon_spi_device_init(struct efx_nic *efx,
-                                 struct efx_spi_device **spi_device_ret,
+static void falcon_spi_device_init(struct efx_nic *efx,
+                                 struct efx_spi_device *spi_device,
                                  unsigned int device_id, u32 device_type)
 {
-       struct efx_spi_device *spi_device;
-
        if (device_type != 0) {
-               spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL);
-               if (!spi_device)
-                       return -ENOMEM;
                spi_device->device_id = device_id;
                spi_device->size =
                        1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE);
@@ -1200,27 +1248,15 @@ static int falcon_spi_device_init(struct efx_nic *efx,
                        1 << SPI_DEV_TYPE_FIELD(device_type,
                                                SPI_DEV_TYPE_BLOCK_SIZE);
        } else {
-               spi_device = NULL;
+               spi_device->size = 0;
        }
-
-       kfree(*spi_device_ret);
-       *spi_device_ret = spi_device;
-       return 0;
-}
-
-static void falcon_remove_spi_devices(struct efx_nic *efx)
-{
-       kfree(efx->spi_eeprom);
-       efx->spi_eeprom = NULL;
-       kfree(efx->spi_flash);
-       efx->spi_flash = NULL;
 }
 
 /* Extract non-volatile configuration */
 static int falcon_probe_nvconfig(struct efx_nic *efx)
 {
+       struct falcon_nic_data *nic_data = efx->nic_data;
        struct falcon_nvconfig *nvconfig;
-       int board_rev;
        int rc;
 
        nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
@@ -1228,55 +1264,32 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
                return -ENOMEM;
 
        rc = falcon_read_nvram(efx, nvconfig);
-       if (rc == -EINVAL) {
-               netif_err(efx, probe, efx->net_dev,
-                         "NVRAM is invalid therefore using defaults\n");
-               efx->phy_type = PHY_TYPE_NONE;
-               efx->mdio.prtad = MDIO_PRTAD_NONE;
-               board_rev = 0;
-               rc = 0;
-       } else if (rc) {
-               goto fail1;
-       } else {
-               struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2;
-               struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3;
-
-               efx->phy_type = v2->port0_phy_type;
-               efx->mdio.prtad = v2->port0_phy_addr;
-               board_rev = le16_to_cpu(v2->board_revision);
-
-               if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
-                       rc = falcon_spi_device_init(
-                               efx, &efx->spi_flash, FFE_AB_SPI_DEVICE_FLASH,
-                               le32_to_cpu(v3->spi_device_type
-                                           [FFE_AB_SPI_DEVICE_FLASH]));
-                       if (rc)
-                               goto fail2;
-                       rc = falcon_spi_device_init(
-                               efx, &efx->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM,
-                               le32_to_cpu(v3->spi_device_type
-                                           [FFE_AB_SPI_DEVICE_EEPROM]));
-                       if (rc)
-                               goto fail2;
-               }
+       if (rc)
+               goto out;
+
+       efx->phy_type = nvconfig->board_v2.port0_phy_type;
+       efx->mdio.prtad = nvconfig->board_v2.port0_phy_addr;
+
+       if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
+               falcon_spi_device_init(
+                       efx, &nic_data->spi_flash, FFE_AB_SPI_DEVICE_FLASH,
+                       le32_to_cpu(nvconfig->board_v3
+                                   .spi_device_type[FFE_AB_SPI_DEVICE_FLASH]));
+               falcon_spi_device_init(
+                       efx, &nic_data->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM,
+                       le32_to_cpu(nvconfig->board_v3
+                                   .spi_device_type[FFE_AB_SPI_DEVICE_EEPROM]));
        }
 
        /* Read the MAC addresses */
-       memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN);
+       memcpy(efx->net_dev->perm_addr, nvconfig->mac_address[0], ETH_ALEN);
 
        netif_dbg(efx, probe, efx->net_dev, "PHY is %d phy_id %d\n",
                  efx->phy_type, efx->mdio.prtad);
 
-       rc = falcon_probe_board(efx, board_rev);
-       if (rc)
-               goto fail2;
-
-       kfree(nvconfig);
-       return 0;
-
- fail2:
-       falcon_remove_spi_devices(efx);
- fail1:
+       rc = falcon_probe_board(efx,
+                               le16_to_cpu(nvconfig->board_v2.board_revision));
+out:
        kfree(nvconfig);
        return rc;
 }
@@ -1284,6 +1297,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
 /* Probe all SPI devices on the NIC */
 static void falcon_probe_spi_devices(struct efx_nic *efx)
 {
+       struct falcon_nic_data *nic_data = efx->nic_data;
        efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
        int boot_dev;
 
@@ -1312,12 +1326,14 @@ static void falcon_probe_spi_devices(struct efx_nic *efx)
                efx_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
        }
 
+       mutex_init(&nic_data->spi_lock);
+
        if (boot_dev == FFE_AB_SPI_DEVICE_FLASH)
-               falcon_spi_device_init(efx, &efx->spi_flash,
+               falcon_spi_device_init(efx, &nic_data->spi_flash,
                                       FFE_AB_SPI_DEVICE_FLASH,
                                       default_flash_type);
        if (boot_dev == FFE_AB_SPI_DEVICE_EEPROM)
-               falcon_spi_device_init(efx, &efx->spi_eeprom,
+               falcon_spi_device_init(efx, &nic_data->spi_eeprom,
                                       FFE_AB_SPI_DEVICE_EEPROM,
                                       large_eeprom_type);
 }
@@ -1382,7 +1398,7 @@ static int falcon_probe_nic(struct efx_nic *efx)
        }
 
        /* Now we can reset the NIC */
-       rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
+       rc = __falcon_reset_hw(efx, RESET_TYPE_ALL);
        if (rc) {
                netif_err(efx, probe, efx->net_dev, "failed to reset NIC\n");
                goto fail3;
@@ -1404,8 +1420,11 @@ static int falcon_probe_nic(struct efx_nic *efx)
 
        /* Read in the non-volatile configuration */
        rc = falcon_probe_nvconfig(efx);
-       if (rc)
+       if (rc) {
+               if (rc == -EINVAL)
+                       netif_err(efx, probe, efx->net_dev, "NVRAM is invalid\n");
                goto fail5;
+       }
 
        /* Initialise I2C adapter */
        board = falcon_board(efx);
@@ -1437,7 +1456,6 @@ static int falcon_probe_nic(struct efx_nic *efx)
        BUG_ON(i2c_del_adapter(&board->i2c_adap));
        memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
  fail5:
-       falcon_remove_spi_devices(efx);
        efx_nic_free_buffer(efx, &efx->irq_status);
  fail4:
  fail3:
@@ -1591,10 +1609,9 @@ static void falcon_remove_nic(struct efx_nic *efx)
        BUG_ON(rc);
        memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
 
-       falcon_remove_spi_devices(efx);
        efx_nic_free_buffer(efx, &efx->irq_status);
 
-       falcon_reset_hw(efx, RESET_TYPE_ALL);
+       __falcon_reset_hw(efx, RESET_TYPE_ALL);
 
        /* Release the second function after the reset */
        if (nic_data->pci_dev2) {
@@ -1705,6 +1722,7 @@ struct efx_nic_type falcon_a1_nic_type = {
        .reset = falcon_reset_hw,
        .probe_port = falcon_probe_port,
        .remove_port = falcon_remove_port,
+       .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,
@@ -1745,6 +1763,7 @@ struct efx_nic_type falcon_b0_nic_type = {
        .reset = falcon_reset_hw,
        .probe_port = falcon_probe_port,
        .remove_port = falcon_remove_port,
+       .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,