/** * ixgbe_dbg_netdev_ops_write - write into netdev_ops datum * @filp: the opened file * @buffer: where to find the user's data * @count: the length of the user's data * @ppos: file position offset **/ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; int bytes_not_copied; /* don't allow partial writes */ if (*ppos != 0) return 0; if (count >= sizeof(ixgbe_dbg_netdev_ops_buf)) return -ENOSPC; bytes_not_copied = copy_from_user(ixgbe_dbg_netdev_ops_buf, buffer, count); if (bytes_not_copied < 0) return bytes_not_copied; else if (bytes_not_copied < count) count -= bytes_not_copied; else return -ENOSPC; ixgbe_dbg_netdev_ops_buf[count] = '\0'; if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev); e_dev_info("tx_timeout called\n"); } else { e_dev_info("Unknown command: %s\n", ixgbe_dbg_netdev_ops_buf); e_dev_info("Available commands:\n"); e_dev_info(" tx_timeout\n"); } return count; }
/** * ixgbe_init_interrupt_scheme - Determine proper interrupt scheme * @adapter: board private structure to initialize * * We determine which interrupt scheme to use based on... * - Kernel support (MSI, MSI-X) * - which can be user-defined (via MODULE_PARAM) * - Hardware queue count (num_*_queues) * - defined by miscellaneous hardware support/features (RSS, etc.) **/ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) { int err; /* Number of supported queues */ ixgbe_set_num_queues(adapter); /* Set interrupt mode */ ixgbe_set_interrupt_capability(adapter); err = ixgbe_alloc_q_vectors(adapter); if (err) { e_dev_err("Unable to allocate memory for queue vectors\n"); goto err_alloc_q_vectors; } ixgbe_cache_ring_register(adapter); e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u\n", (adapter->num_rx_queues > 1) ? "Enabled" : "Disabled", adapter->num_rx_queues, adapter->num_tx_queues); set_bit(__IXGBE_DOWN, &adapter->state); return 0; err_alloc_q_vectors: ixgbe_reset_interrupt_capability(adapter); return err; }
/** * ixgbe_dbg_reg_ops_write - write into reg_ops datum * @filp: the opened file * @buffer: where to find the user's data * @count: the length of the user's data * @ppos: file position offset **/ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; int len; /* don't allow partial writes */ if (*ppos != 0) return 0; if (count >= sizeof(ixgbe_dbg_reg_ops_buf)) return -ENOSPC; len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf, sizeof(ixgbe_dbg_reg_ops_buf)-1, ppos, buffer, count); if (len < 0) return len; ixgbe_dbg_reg_ops_buf[len] = '\0'; if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) { u32 reg, value; int cnt; cnt = sscanf(&ixgbe_dbg_reg_ops_buf[5], "%x %x", ®, &value); if (cnt == 2) { IXGBE_WRITE_REG(&adapter->hw, reg, value); value = IXGBE_READ_REG(&adapter->hw, reg); e_dev_info("write: 0x%08x = 0x%08x\n", reg, value); } else { e_dev_info("write <reg> <value>\n"); } } else if (strncmp(ixgbe_dbg_reg_ops_buf, "read", 4) == 0) { u32 reg, value; int cnt; cnt = sscanf(&ixgbe_dbg_reg_ops_buf[4], "%x", ®); if (cnt == 1) { value = IXGBE_READ_REG(&adapter->hw, reg); e_dev_info("read 0x%08x = 0x%08x\n", reg, value); } else { e_dev_info("read <reg>\n"); } } else { e_dev_info("Unknown command %s\n", ixgbe_dbg_reg_ops_buf); e_dev_info("Available commands:\n"); e_dev_info(" read <reg>\n"); e_dev_info(" write <reg> <value>\n"); } return count; }
/** * ixgbe_ptp_init * @adapter - the ixgbe private adapter structure * * This function performs the required steps for enabling ptp * support. If ptp support has already been loaded it simply calls the * cyclecounter init routine and exits. */ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; switch (adapter->hw.mac.type) { case ixgbe_mac_X540: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 1; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; adapter->ptp_caps.gettime = ixgbe_ptp_gettime; adapter->ptp_caps.settime = ixgbe_ptp_settime; adapter->ptp_caps.enable = ixgbe_ptp_enable; break; case ixgbe_mac_82599EB: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime; adapter->ptp_caps.gettime = ixgbe_ptp_gettime; adapter->ptp_caps.settime = ixgbe_ptp_settime; adapter->ptp_caps.enable = ixgbe_ptp_enable; break; default: adapter->ptp_clock = NULL; return; } spin_lock_init(&adapter->tmreg_lock); ixgbe_ptp_start_cyclecounter(adapter); /* (Re)start the overflow check */ adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps); if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; e_dev_err("ptp_clock_register failed\n"); } else e_dev_info("registered PHC device on %s\n", netdev->name); return; }
/** * ixgbe_ptp_stop - destroy the ptp_clock device * @adapter: pointer to adapter struct * * Completely destroy the ptp_clock device, and disable all PTP related * features. Intended to be run when the device is being closed. */ void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) { /* first, suspend ptp activity */ ixgbe_ptp_suspend(adapter); /* now destroy the ptp clock device */ if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); adapter->ptp_clock = NULL; e_dev_info("removed PHC on %s\n", adapter->netdev->name); } }
/** * ixgbe_ptp_stop - disable ptp device and stop the overflow check * @adapter: pointer to adapter struct * * this function stops the ptp support, and cancels the delayed work. */ void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) { ixgbe_ptp_disable_sdp(&adapter->hw); /* stop the overflow check task */ adapter->flags2 &= ~IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); adapter->ptp_clock = NULL; e_dev_info("removed PHC on %s\n", adapter->netdev->name); } }
/** * ixgbe_dbg_netdev_ops_write - write into netdev_ops datum * @filp: the opened file * @buffer: where to find the user's data * @count: the length of the user's data * @ppos: file position offset **/ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; int len; /* don't allow partial writes */ if (*ppos != 0) return 0; if (count >= sizeof(ixgbe_dbg_netdev_ops_buf)) return -ENOSPC; len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf, sizeof(ixgbe_dbg_netdev_ops_buf)-1, ppos, buffer, count); if (len < 0) return len; ixgbe_dbg_netdev_ops_buf[len] = '\0'; if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { #ifdef HAVE_NET_DEVICE_OPS adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev); #else adapter->netdev->tx_timeout(adapter->netdev); #endif /* HAVE_NET_DEVICE_OPS */ e_dev_info("tx_timeout called\n"); } else { e_dev_info("Unknown command: %s\n", ixgbe_dbg_netdev_ops_buf); e_dev_info("Available commands:\n"); e_dev_info(" tx_timeout\n"); } return count; }
static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter, int expected_gts) { struct ixgbe_hw *hw = &adapter->hw; int max_gts = 0; enum pci_bus_speed speed = PCI_SPEED_UNKNOWN; enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN; struct pci_dev *pdev; /* Some devices are not connected over PCIe and thus do not negotiate * speed. These devices do not have valid bus info, and thus any report * we generate may not be correct. */ if (hw->bus.type == ixgbe_bus_type_internal) return; /* determine whether to use the parent device */ if (ixgbe_pcie_from_parent(&adapter->hw)) pdev = adapter->pdev->bus->parent->self; else pdev = adapter->pdev; if (pcie_get_minimum_link(pdev, &speed, &width) || speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) { e_dev_warn("Unable to determine PCI Express bandwidth.\n"); return; } switch (speed) { case PCIE_SPEED_2_5GT: /* 8b/10b encoding reduces max throughput by 20% */ max_gts = 2 * width; break; case PCIE_SPEED_5_0GT: /* 8b/10b encoding reduces max throughput by 20% */ max_gts = 4 * width; break; case PCIE_SPEED_8_0GT: /* 128b/130b encoding reduces throughput by less than 2% */ max_gts = 8 * width; break; default: e_dev_warn("Unable to determine PCI Express bandwidth.\n"); return; } e_dev_info("PCI Express bandwidth of %dGT/s available\n", max_gts); e_dev_info("(Speed:%s, Width: x%d, Encoding Loss:%s)\n", (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : "Unknown"), width, (speed == PCIE_SPEED_2_5GT ? "20%" : speed == PCIE_SPEED_5_0GT ? "20%" : speed == PCIE_SPEED_8_0GT ? "<2%" : "Unknown")); if (max_gts < expected_gts) { e_dev_warn("This is not sufficient for optimal performance of this card.\n"); e_dev_warn("For optimal performance, at least %dGT/s of bandwidth is required.\n", expected_gts); e_dev_warn("A slot with more lanes and/or higher speed is suggested.\n"); } }
static long ixgbe_ptp_create_clock(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; long err; /* do nothing if we already have a clock device */ if (!IS_ERR_OR_NULL(adapter->ptp_clock)) return 0; switch (adapter->hw.mac.type) { case ixgbe_mac_X540: snprintf(adapter->ptp_caps.name, sizeof(adapter->ptp_caps.name), "%s", netdev->name); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 1; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime_82599; adapter->ptp_caps.gettime = ixgbe_ptp_gettime_82599; adapter->ptp_caps.settime = ixgbe_ptp_settime_82599; adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; adapter->ptp_setup_sdp = ixgbe_ptp_setup_sdp_X540; break; case ixgbe_mac_82599EB: snprintf(adapter->ptp_caps.name, sizeof(adapter->ptp_caps.name), "%s", netdev->name); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.n_per_out = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq_82599; adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime_82599; adapter->ptp_caps.gettime = ixgbe_ptp_gettime_82599; adapter->ptp_caps.settime = ixgbe_ptp_settime_82599; adapter->ptp_caps.enable = ixgbe_ptp_feature_enable; break; default: adapter->ptp_clock = NULL; adapter->ptp_setup_sdp = NULL; return -EOPNOTSUPP; } adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, pci_dev_to_dev(adapter->pdev)); if (IS_ERR(adapter->ptp_clock)) { err = PTR_ERR(adapter->ptp_clock); adapter->ptp_clock = NULL; e_dev_err("ptp_clock_register failed\n"); return err; } else e_dev_info("registered PHC device on %s\n", netdev->name); /* Set the default timestamp mode to disabled here. We do this in * create_clock instead of initialization, because we don't want to * override the previous settings during a suspend/resume cycle. */ adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; return 0; }