* [net-next v2 6/8] ixgbe: add syfs interface for to export read only driver information
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Don Skidmore, netdev, gospo, sassmann, bhutchings, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Don Skidmore <donald.c.skidmore@intel.com>
This patch exports non-thermal (which was done via hwmon in an earlier
patch) data to sysfs which isn't readily available elsewhere. All of the
fields are read only as this interface is to only export driver data.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Tested-by: Stephen Ko <stephen.s.ko@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c | 322 +++++++++++++++++++++++-
1 files changed, 317 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
index aa41fb7..6601986 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
@@ -41,6 +41,310 @@
* This file provides a sysfs interface to export information from the
* driver. The information presented is READ-ONLY.
*/
+
+static struct net_device *ixgbe_get_netdev(struct kobject *kobj)
+{
+ struct net_device *netdev;
+ struct kobject *parent = kobj->parent;
+ struct device *device_info_kobj;
+
+ if (kobj == NULL)
+ return NULL;
+
+ device_info_kobj = container_of(parent, struct device, kobj);
+ if (device_info_kobj == NULL)
+ return NULL;
+
+ netdev = container_of(device_info_kobj, struct net_device, dev);
+ return netdev;
+}
+
+static struct ixgbe_adapter *ixgbe_get_adapter(struct kobject *kobj)
+{
+ struct ixgbe_adapter *adapter;
+ struct net_device *netdev = ixgbe_get_netdev(kobj);
+
+ if (netdev == NULL)
+ return NULL;
+
+ adapter = netdev_priv(netdev);
+ return adapter;
+}
+
+static ssize_t ixgbe_rxupacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_TPR));
+}
+
+static ssize_t ixgbe_rxmpacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_MPRC));
+}
+
+static ssize_t ixgbe_rxbpacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_BPRC));
+}
+
+static ssize_t ixgbe_txupacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_TPT));
+}
+
+static ssize_t ixgbe_txmpacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_MPTC));
+}
+
+static ssize_t ixgbe_txbpacks(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", IXGBE_READ_REG(hw, IXGBE_BPTC));
+}
+
+static ssize_t ixgbe_maclla1(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_hw *hw;
+ u16 eeprom_buff[6];
+ int first_word = 0x37;
+ int word_count = 6;
+ int rc;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ hw = &adapter->hw;
+ if (hw == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no hw data\n");
+
+ rc = hw->eeprom.ops.read_buffer(hw, first_word, word_count,
+ eeprom_buff);
+ if (rc)
+ return snprintf(buf, PAGE_SIZE, "error: reading buffer\n");
+
+ switch (hw->bus.func) {
+ case 0:
+ return snprintf(buf, PAGE_SIZE, "0x%04X%04X%04X\n",
+ eeprom_buff[0],
+ eeprom_buff[1],
+ eeprom_buff[2]);
+ case 1:
+ return snprintf(buf, PAGE_SIZE, "0x%04X%04X%04X\n",
+ eeprom_buff[3],
+ eeprom_buff[4],
+ eeprom_buff[5]);
+ }
+
+ return snprintf(buf, PAGE_SIZE, "unexpected port %d\n", hw->bus.func);
+}
+
+static ssize_t ixgbe_txdscqsz(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", adapter->tx_ring[0]->count);
+}
+
+static ssize_t ixgbe_rxdscqsz(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", adapter->rx_ring[0]->count);
+}
+
+static ssize_t ixgbe_rxqavg(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ int index;
+ int diff = 0;
+ u16 ntc;
+ u16 ntu;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ for (index = 0; index < adapter->num_rx_queues; index++) {
+ ntc = adapter->rx_ring[index]->next_to_clean;
+ ntu = adapter->rx_ring[index]->next_to_use;
+
+ if (ntc >= ntu)
+ diff += (ntc - ntu);
+ else
+ diff += (adapter->rx_ring[index]->count - ntu + ntc);
+ }
+
+ if (adapter->num_rx_queues <= 0)
+ return snprintf(buf, PAGE_SIZE,
+ "can't calculate, number of queues %d\n",
+ adapter->num_rx_queues);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", diff/adapter->num_rx_queues);
+}
+
+static ssize_t ixgbe_txqavg(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ int index;
+ int diff = 0;
+ u16 ntc;
+ u16 ntu;
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ for (index = 0; index < adapter->num_tx_queues; index++) {
+ ntc = adapter->tx_ring[index]->next_to_clean;
+ ntu = adapter->tx_ring[index]->next_to_use;
+
+ if (ntc >= ntu)
+ diff += (ntc - ntu);
+ else
+ diff += (adapter->tx_ring[index]->count - ntu + ntc);
+ }
+
+ if (adapter->num_tx_queues <= 0)
+ return snprintf(buf, PAGE_SIZE,
+ "can't calculate, number of queues %d\n",
+ adapter->num_tx_queues);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", diff/adapter->num_tx_queues);
+}
+
+static ssize_t ixgbe_funcnbr(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct ixgbe_adapter *adapter = ixgbe_get_adapter(kobj);
+
+ if (adapter == NULL)
+ return snprintf(buf, PAGE_SIZE, "error: no adapter\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", adapter->num_vfs);
+}
+
+/* Initialize the attributes */
+static struct kobj_attribute ixgbe_sysfs_rxupacks_attr =
+ __ATTR(rxupacks, 0444, ixgbe_rxupacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_rxmpacks_attr =
+ __ATTR(rxmpacks, 0444, ixgbe_rxmpacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_rxbpacks_attr =
+ __ATTR(rxbpacks, 0444, ixgbe_rxbpacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_txupacks_attr =
+ __ATTR(txupacks, 0444, ixgbe_txupacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_txmpacks_attr =
+ __ATTR(txmpacks, 0444, ixgbe_txmpacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_txbpacks_attr =
+ __ATTR(txbpacks, 0444, ixgbe_txbpacks, NULL);
+static struct kobj_attribute ixgbe_sysfs_maclla1_attr =
+ __ATTR(maclla1, 0444, ixgbe_maclla1, NULL);
+static struct kobj_attribute ixgbe_sysfs_txdscqsz_attr =
+ __ATTR(txdscqsz, 0444, ixgbe_txdscqsz, NULL);
+static struct kobj_attribute ixgbe_sysfs_rxdscqsz_attr =
+ __ATTR(rxdscqsz, 0444, ixgbe_rxdscqsz, NULL);
+static struct kobj_attribute ixgbe_sysfs_txqavg_attr =
+ __ATTR(txqavg, 0444, ixgbe_txqavg, NULL);
+static struct kobj_attribute ixgbe_sysfs_rxqavg_attr =
+ __ATTR(rxqavg, 0444, ixgbe_rxqavg, NULL);
+static struct kobj_attribute ixgbe_sysfs_funcnbr_attr =
+ __ATTR(funcnbr, 0444, ixgbe_funcnbr, NULL);
+
+static struct attribute *attrs[] = {
+ &ixgbe_sysfs_rxupacks_attr.attr,
+ &ixgbe_sysfs_rxmpacks_attr.attr,
+ &ixgbe_sysfs_rxbpacks_attr.attr,
+ &ixgbe_sysfs_txupacks_attr.attr,
+ &ixgbe_sysfs_txmpacks_attr.attr,
+ &ixgbe_sysfs_txbpacks_attr.attr,
+ &ixgbe_sysfs_maclla1_attr.attr,
+ &ixgbe_sysfs_txdscqsz_attr.attr,
+ &ixgbe_sysfs_rxdscqsz_attr.attr,
+ &ixgbe_sysfs_txqavg_attr.attr,
+ &ixgbe_sysfs_rxqavg_attr.attr,
+ &ixgbe_sysfs_funcnbr_attr.attr,
+ NULL
+};
+
+/* add attributes to a group */
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
#ifdef CONFIG_IXGBE_HWMON
/* hwmon callback functions */
@@ -185,8 +489,11 @@ static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter)
hwmon_device_unregister(adapter->ixgbe_hwmon_buff.device);
#endif /* CONFIG_IXGBE_HWMON */
- if (adapter->info_kobj != NULL)
+ if (adapter->info_kobj != NULL) {
+ sysfs_remove_group(adapter->info_kobj, &attr_group);
kobject_put(adapter->info_kobj);
+ adapter->info_kobj = NULL;
+ }
}
/* called from ixgbe_main.c */
@@ -213,17 +520,22 @@ int ixgbe_sysfs_init(struct ixgbe_adapter *adapter)
goto err;
}
+ rc = sysfs_create_group(adapter->info_kobj, &attr_group);
+ if (rc)
+ goto err;
+
#ifdef CONFIG_IXGBE_HWMON
/* If this method isn't defined we don't support thermals */
if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) {
- rc = -EPERM;
- goto err;
+ goto exit;
}
/* Don't create thermal hwmon interface if no sensors present */
rc = adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw);
- if (rc)
- goto err;
+ if (rc) {
+ rc = 0;
+ goto exit;
+ }
/*
* Allocation space for max attributs
--
1.7.7.6
^ permalink raw reply related
* [net-next v2 5/8] ixgbe: add hwmon interface to export thermal data
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Don Skidmore, netdev, gospo, sassmann, bhutchings, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Don Skidmore <donald.c.skidmore@intel.com>
Some of our adapters have thermal data available, this patch exports
this data via hwmon sysfs interface. Other sysfs read-only file follow in
another patch. Some of the functions introduced there take that into
account.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Tested-by: Stephen Ko <stephen.s.ko@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/Kconfig | 8 +
drivers/net/ethernet/intel/ixgbe/Makefile | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 26 +++
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 2 +
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 2 +
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 10 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +
drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c | 271 +++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 2 +
9 files changed, 322 insertions(+), 7 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 74215c0..546efe3 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -193,6 +193,14 @@ config IXGBE
To compile this driver as a module, choose M here. The module
will be called ixgbe.
+config IXGBE_HWMON
+ bool "Intel(R) 10GbE PCI Express adapters HWMON support"
+ default y
+ depends on IXGBE && HWMON && !(IXGBE=y && HWMON=m)
+ ---help---
+ Say Y if you want to expose the thermal sensor data on some of
+ our cards, via a hwmon sysfs interface.
+
config IXGBE_DCA
bool "Direct Cache Access (DCA) Support"
default y
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 8be1d1b..0708d7e 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
- ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o
+ ixgbe_mbx.o ixgbe_x540.o ixgbe_sysfs.o ixgbe_lib.o
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe_dcb_82599.o ixgbe_dcb_nl.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 8e082f2..89cebc8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -331,6 +331,26 @@ struct ixgbe_q_vector {
/* for dynamic allocation of rings associated with this q_vector */
struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp;
};
+#ifdef CONFIG_IXGBE_HWMON
+
+#define IXGBE_HWMON_TYPE_LOC 0
+#define IXGBE_HWMON_TYPE_TEMP 1
+#define IXGBE_HWMON_TYPE_CAUTION 2
+#define IXGBE_HWMON_TYPE_MAX 3
+
+struct hwmon_attr {
+ struct device_attribute dev_attr;
+ struct ixgbe_hw *hw;
+ struct ixgbe_thermal_diode_data *sensor;
+ char name[12];
+};
+
+struct hwmon_buff {
+ struct device *device;
+ struct hwmon_attr *hwmon_list;
+ unsigned int n_hwmon;
+};
+#endif /* CONFIG_IXGBE_HWMON */
/*
* microsecond values for various ITR rates shifted by 2 to fit itr register
@@ -535,6 +555,10 @@ struct ixgbe_adapter {
u32 timer_event_accumulator;
u32 vferr_refcount;
+ struct kobject *info_kobj;
+#ifdef CONFIG_IXGBE_HWMON
+ struct hwmon_buff ixgbe_hwmon_buff;
+#endif /* CONFIG_IXGBE_HWMON */
};
struct ixgbe_fdir_filter {
@@ -635,6 +659,8 @@ extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
#endif
extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
extern void ixgbe_do_reset(struct net_device *netdev);
+extern void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter);
+extern int ixgbe_sysfs_init(struct ixgbe_adapter *adapter);
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fso(struct ixgbe_ring *tx_ring,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 56fd468..6175845 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -1277,6 +1277,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
+ .get_thermal_sensor_data = NULL,
+ .init_thermal_sensor_thresh = NULL,
};
static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 9c14685..dee64d2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -2119,6 +2119,8 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
+ .get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
+ .init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
};
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 6c6c66e..e2b0519 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -3669,9 +3669,8 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
u8 i;
struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
- /* Only support thermal sensors attached to 82599 physical port 0 */
- if ((hw->mac.type != ixgbe_mac_82599EB) ||
- (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ /* Only support thermal sensors attached to physical port 0 */
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
status = IXGBE_NOT_IMPLEMENTED;
goto out;
}
@@ -3732,9 +3731,8 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
- /* Only support thermal sensors attached to 82599 physical port 0 */
- if ((hw->mac.type != ixgbe_mac_82599EB) ||
- (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ /* Only support thermal sensors attached to physical port 0 */
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
status = IXGBE_NOT_IMPLEMENTED;
goto out;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index aa29edb..e8897cc 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7219,6 +7219,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
e_dev_info("%s\n", ixgbe_default_device_descr);
cards_found++;
+
+ if (ixgbe_sysfs_init(adapter))
+ e_err(probe, "failed to allocate sysfs resources\n");
+
return 0;
err_register:
@@ -7265,6 +7269,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
}
#endif
+ ixgbe_sysfs_exit(adapter);
+
#ifdef IXGBE_FCOE
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
ixgbe_cleanup_fcoe(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
new file mode 100644
index 0000000..aa41fb7
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
@@ -0,0 +1,271 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2012 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgbe.h"
+#include "ixgbe_common.h"
+#include "ixgbe_type.h"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/hwmon.h>
+
+/*
+ * This file provides a sysfs interface to export information from the
+ * driver. The information presented is READ-ONLY.
+ */
+#ifdef CONFIG_IXGBE_HWMON
+
+/* hwmon callback functions */
+static ssize_t ixgbe_hwmon_show_location(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ return sprintf(buf, "loc%u\n",
+ ixgbe_attr->sensor->location);
+}
+
+static ssize_t ixgbe_hwmon_show_temp(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value;
+
+ /* reset the temp field */
+ ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw);
+
+ value = ixgbe_attr->sensor->temp;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value = ixgbe_attr->sensor->caution_thresh;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value = ixgbe_attr->sensor->max_op_thresh;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+/*
+ * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
+ * @ adapter: pointer to the adapter structure
+ * @ offset: offset in the eeprom sensor data table
+ * @ type: type of sensor data to display
+ *
+ * For each file we want in hwmon's sysfs interface we need a device_attribute
+ * This is included in our hwmon_attr struct that contains the references to
+ * the data structures we need to get the data to display.
+ */
+static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter,
+ unsigned int offset, int type) {
+ int rc;
+ unsigned int n_attr;
+ struct hwmon_attr *ixgbe_attr;
+
+ n_attr = adapter->ixgbe_hwmon_buff.n_hwmon;
+ ixgbe_attr = &adapter->ixgbe_hwmon_buff.hwmon_list[n_attr];
+
+ switch (type) {
+ case IXGBE_HWMON_TYPE_LOC:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_label", offset);
+ break;
+ case IXGBE_HWMON_TYPE_TEMP:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_input", offset);
+ break;
+ case IXGBE_HWMON_TYPE_CAUTION:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_max", offset);
+ break;
+ case IXGBE_HWMON_TYPE_MAX:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_crit", offset);
+ break;
+ default:
+ rc = -EPERM;
+ return rc;
+ }
+
+ /* These always the same regardless of type */
+ ixgbe_attr->sensor =
+ &adapter->hw.mac.thermal_sensor_data.sensor[offset];
+ ixgbe_attr->hw = &adapter->hw;
+ ixgbe_attr->dev_attr.store = NULL;
+ ixgbe_attr->dev_attr.attr.mode = S_IRUGO;
+ ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name;
+
+ rc = device_create_file(&adapter->pdev->dev,
+ &ixgbe_attr->dev_attr);
+
+ if (rc == 0)
+ ++adapter->ixgbe_hwmon_buff.n_hwmon;
+
+ return rc;
+}
+#endif /* CONFIG_IXGBE_HWMON */
+
+static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_HWMON
+ int i;
+#endif /* CONFIG_IXGBE_HWMON */
+
+ if (adapter == NULL)
+ return;
+#ifdef CONFIG_IXGBE_HWMON
+
+ for (i = 0; i < adapter->ixgbe_hwmon_buff.n_hwmon; i++) {
+ device_remove_file(&adapter->pdev->dev,
+ &adapter->ixgbe_hwmon_buff.hwmon_list[i].dev_attr);
+ }
+
+ kfree(adapter->ixgbe_hwmon_buff.hwmon_list);
+
+ if (adapter->ixgbe_hwmon_buff.device)
+ hwmon_device_unregister(adapter->ixgbe_hwmon_buff.device);
+#endif /* CONFIG_IXGBE_HWMON */
+
+ if (adapter->info_kobj != NULL)
+ kobject_put(adapter->info_kobj);
+}
+
+/* called from ixgbe_main.c */
+void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter)
+{
+ ixgbe_sysfs_del_adapter(adapter);
+}
+
+/* called from ixgbe_main.c */
+int ixgbe_sysfs_init(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_HWMON
+ struct hwmon_buff *ixgbe_hwmon = &adapter->ixgbe_hwmon_buff;
+ unsigned int i;
+ int n_attrs;
+#endif /* CONFIG_IXGBE_HWMON */
+ struct net_device *netdev = adapter->netdev;
+ int rc = 0;
+
+ /* create info kobj and attribute listings in kobj */
+ adapter->info_kobj = kobject_create_and_add("info", &netdev->dev.kobj);
+ if (adapter->info_kobj == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+#ifdef CONFIG_IXGBE_HWMON
+ /* If this method isn't defined we don't support thermals */
+ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) {
+ rc = -EPERM;
+ goto err;
+ }
+
+ /* Don't create thermal hwmon interface if no sensors present */
+ rc = adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw);
+ if (rc)
+ goto err;
+
+ /*
+ * Allocation space for max attributs
+ * max num sensors * values (loc, temp, max, caution)
+ */
+ n_attrs = IXGBE_MAX_SENSORS * 4;
+ ixgbe_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
+ GFP_KERNEL);
+ if (!ixgbe_hwmon->hwmon_list) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ ixgbe_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
+ if (IS_ERR(ixgbe_hwmon->device)) {
+ rc = PTR_ERR(ixgbe_hwmon->device);
+ goto err;
+ }
+
+ for (i = 0; i < IXGBE_MAX_SENSORS; i++) {
+ /*
+ * Only create hwmon sysfs entries for sensors that have
+ * meaningful data for.
+ */
+ if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
+ continue;
+
+ /* Bail if any hwmon attr struct fails to initialize */
+ rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX);
+ if (rc)
+ goto err;
+ }
+#endif /* CONFIG_IXGBE_HWMON */
+
+ goto exit;
+
+err:
+ ixgbe_sysfs_del_adapter(adapter);
+exit:
+ return rc;
+}
+
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 97a9914..f90ec07 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -849,6 +849,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.release_swfw_sync = &ixgbe_release_swfw_sync_X540,
.disable_rx_buff = &ixgbe_disable_rx_buff_generic,
.enable_rx_buff = &ixgbe_enable_rx_buff_generic,
+ .get_thermal_sensor_data = NULL,
+ .init_thermal_sensor_thresh = NULL,
};
static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
--
1.7.7.6
^ permalink raw reply related
* [net-next v2 4/8] ixgbe: add support functions to access thermal data
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Don Skidmore, netdev, gospo, sassmann, bhutchings, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Don Skidmore <donald.c.skidmore@intel.com>
Some 82599 adapters contain thermal data that we can get to via
an i2c interface. These functions provide support to get at that
data. A following patch will export this data.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 171 +++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 13 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 40 ++++++
3 files changed, 224 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index e598881..6c6c66e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -3604,3 +3604,174 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
}
+
+static const u8 ixgbe_emc_temp_data[4] = {
+ IXGBE_EMC_INTERNAL_DATA,
+ IXGBE_EMC_DIODE1_DATA,
+ IXGBE_EMC_DIODE2_DATA,
+ IXGBE_EMC_DIODE3_DATA
+};
+static const u8 ixgbe_emc_therm_limit[4] = {
+ IXGBE_EMC_INTERNAL_THERM_LIMIT,
+ IXGBE_EMC_DIODE1_THERM_LIMIT,
+ IXGBE_EMC_DIODE2_THERM_LIMIT,
+ IXGBE_EMC_DIODE3_THERM_LIMIT
+};
+
+/**
+ * ixgbe_get_ets_data - Extracts the ETS bit data
+ * @hw: pointer to hardware structure
+ * @ets_cfg: extected ETS data
+ * @ets_offset: offset of ETS data
+ *
+ * Returns error code.
+ **/
+static s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg,
+ u16 *ets_offset)
+{
+ s32 status = 0;
+
+ status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset);
+ if (status)
+ goto out;
+
+ if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
+ if (status)
+ goto out;
+
+ if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data
+ * @hw: pointer to hardware structure
+ *
+ * Returns the thermal sensor data structure
+ **/
+s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u16 ets_offset;
+ u16 ets_cfg;
+ u16 ets_sensor;
+ u8 num_sensors;
+ u8 i;
+ struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+ /* Only support thermal sensors attached to 82599 physical port 0 */
+ if ((hw->mac.type != ixgbe_mac_82599EB) ||
+ (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
+ if (status)
+ goto out;
+
+ num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+ if (num_sensors > IXGBE_MAX_SENSORS)
+ num_sensors = IXGBE_MAX_SENSORS;
+
+ for (i = 0; i < num_sensors; i++) {
+ u8 sensor_index;
+ u8 sensor_location;
+
+ status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
+ &ets_sensor);
+ if (status)
+ goto out;
+
+ sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+ IXGBE_ETS_DATA_INDEX_SHIFT);
+ sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+ IXGBE_ETS_DATA_LOC_SHIFT);
+
+ if (sensor_location != 0) {
+ status = hw->phy.ops.read_i2c_byte(hw,
+ ixgbe_emc_temp_data[sensor_index],
+ IXGBE_I2C_THERMAL_SENSOR_ADDR,
+ &data->sensor[i].temp);
+ if (status)
+ goto out;
+ }
+ }
+out:
+ return status;
+}
+
+/**
+ * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds
+ * @hw: pointer to hardware structure
+ *
+ * Inits the thermal sensor thresholds according to the NVM map
+ * and save off the threshold and location values into mac.thermal_sensor_data
+ **/
+s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u16 ets_offset;
+ u16 ets_cfg;
+ u16 ets_sensor;
+ u8 low_thresh_delta;
+ u8 num_sensors;
+ u8 therm_limit;
+ u8 i;
+ struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+ memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
+
+ /* Only support thermal sensors attached to 82599 physical port 0 */
+ if ((hw->mac.type != ixgbe_mac_82599EB) ||
+ (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
+ if (status)
+ goto out;
+
+ low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
+ IXGBE_ETS_LTHRES_DELTA_SHIFT);
+ num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+ if (num_sensors > IXGBE_MAX_SENSORS)
+ num_sensors = IXGBE_MAX_SENSORS;
+
+ for (i = 0; i < num_sensors; i++) {
+ u8 sensor_index;
+ u8 sensor_location;
+
+ hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor);
+ sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+ IXGBE_ETS_DATA_INDEX_SHIFT);
+ sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+ IXGBE_ETS_DATA_LOC_SHIFT);
+ therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK;
+
+ hw->phy.ops.write_i2c_byte(hw,
+ ixgbe_emc_therm_limit[sensor_index],
+ IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit);
+
+ if (sensor_location == 0)
+ continue;
+
+ data->sensor[i].location = sensor_location;
+ data->sensor[i].caution_thresh = therm_limit;
+ data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta;
+ }
+out:
+ return status;
+}
+
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index d6d3432..f992777 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -107,6 +107,19 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
u32 headroom, int strategy);
+#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
+#define IXGBE_EMC_INTERNAL_DATA 0x00
+#define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
+#define IXGBE_EMC_DIODE1_DATA 0x01
+#define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19
+#define IXGBE_EMC_DIODE2_DATA 0x23
+#define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A
+#define IXGBE_EMC_DIODE3_DATA 0x2A
+#define IXGBE_EMC_DIODE3_THERM_LIMIT 0x30
+
+s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
+s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
+
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#ifndef writeq
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 4acd9e6..d82e25c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -112,6 +112,27 @@
#define IXGBE_I2C_DATA_OUT 0x00000008
#define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500
+#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
+#define IXGBE_EMC_INTERNAL_DATA 0x00
+#define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
+#define IXGBE_EMC_DIODE1_DATA 0x01
+#define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19
+#define IXGBE_EMC_DIODE2_DATA 0x23
+#define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A
+
+#define IXGBE_MAX_SENSORS 3
+
+struct ixgbe_thermal_diode_data {
+ u8 location;
+ u8 temp;
+ u8 caution_thresh;
+ u8 max_op_thresh;
+};
+
+struct ixgbe_thermal_sensor_data {
+ struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS];
+};
+
/* Interrupt Registers */
#define IXGBE_EICR 0x00800
#define IXGBE_EICS 0x00808
@@ -1678,6 +1699,22 @@ enum {
#define IXGBE_PBANUM0_PTR 0x15
#define IXGBE_PBANUM1_PTR 0x16
#define IXGBE_FREE_SPACE_PTR 0X3E
+
+/* External Thermal Sensor Config */
+#define IXGBE_ETS_CFG 0x26
+#define IXGBE_ETS_LTHRES_DELTA_MASK 0x07C0
+#define IXGBE_ETS_LTHRES_DELTA_SHIFT 6
+#define IXGBE_ETS_TYPE_MASK 0x0038
+#define IXGBE_ETS_TYPE_SHIFT 3
+#define IXGBE_ETS_TYPE_EMC 0x000
+#define IXGBE_ETS_TYPE_EMC_SHIFTED 0x000
+#define IXGBE_ETS_NUM_SENSORS_MASK 0x0007
+#define IXGBE_ETS_DATA_LOC_MASK 0x3C00
+#define IXGBE_ETS_DATA_LOC_SHIFT 10
+#define IXGBE_ETS_DATA_INDEX_MASK 0x0300
+#define IXGBE_ETS_DATA_INDEX_SHIFT 8
+#define IXGBE_ETS_DATA_HTHRESH_MASK 0x00FF
+
#define IXGBE_SAN_MAC_ADDR_PTR 0x28
#define IXGBE_DEVICE_CAPS 0x2C
#define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11
@@ -2775,6 +2812,8 @@ struct ixgbe_mac_operations {
/* Manageability interface */
s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
+ s32 (*get_thermal_sensor_data)(struct ixgbe_hw *);
+ s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw);
};
struct ixgbe_phy_operations {
@@ -2832,6 +2871,7 @@ struct ixgbe_mac_info {
bool orig_link_settings_stored;
bool autotry_restart;
u8 flags;
+ struct ixgbe_thermal_sensor_data thermal_sensor_data;
};
struct ixgbe_phy_info {
--
1.7.7.6
^ permalink raw reply related
* [net-next 3/8] e1000e: fix .ndo_set_rx_mode for 82579
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Bruce Allan, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
Secondary unicast and multicast addresses are added to the Receive
Address registers (RAR) for most parts supported by the driver. For
82579, there is only one actual RAR and a number of Shared Receive Address
registers (SHRAR) that are shared among the driver and f/w which can be
reserved and write-protected by the f/w. On this device, use the SHRARs
that are not taken by f/w for the additional addresses.
Add a MAC ops function pointer infrastructure (similar to other MAC
operations in the driver) for setting RARs, introduce a new rar_set
function for 82579 and convert the existing code that sets RARs on other
devices to a generic rar_set function.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/80003es2lan.c | 1 +
drivers/net/ethernet/intel/e1000e/82571.c | 4 +-
drivers/net/ethernet/intel/e1000e/e1000.h | 2 +-
drivers/net/ethernet/intel/e1000e/hw.h | 5 ++
drivers/net/ethernet/intel/e1000e/ich8lan.c | 72 ++++++++++++++++++++++-
drivers/net/ethernet/intel/e1000e/mac.c | 10 ++--
drivers/net/ethernet/intel/e1000e/netdev.c | 12 ++--
7 files changed, 92 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index a212846..66f9877 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -1439,6 +1439,7 @@ static const struct e1000_mac_operations es2_mac_ops = {
/* setup_physical_interface dependent on media type */
.setup_led = e1000e_setup_led_generic,
.config_collision_dist = e1000e_config_collision_dist_generic,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations es2_phy_ops = {
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index d0ea316..7b02e87 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -1762,7 +1762,8 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
* incoming packets directed to this port are dropped.
* Eventually the LAA will be in RAR[0] and RAR[14].
*/
- e1000e_rar_set(hw, hw->mac.addr, hw->mac.rar_entry_count - 1);
+ hw->mac.ops.rar_set(hw, hw->mac.addr,
+ hw->mac.rar_entry_count - 1);
}
/**
@@ -1926,6 +1927,7 @@ static const struct e1000_mac_operations e82571_mac_ops = {
.setup_led = e1000e_setup_led_generic,
.config_collision_dist = e1000e_config_collision_dist_generic,
.read_mac_addr = e1000_read_mac_addr_82571,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations e82_phy_ops_igp = {
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 1dc2067..1da9bfa 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -576,7 +576,7 @@ extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
u8 *mc_addr_list,
u32 mc_addr_count);
-extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+extern void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw);
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 3a5acb5..00a0ebb 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -200,6 +200,10 @@ enum e1e_registers {
#define E1000_RA (E1000_RAL(0))
E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */
#define E1000_RAH(_n) (E1000_RAH_BASE + ((_n) * 8))
+ E1000_SHRAL_BASE = 0x05438, /* Shared Receive Address Low - RW */
+#define E1000_SHRAL(_n) (E1000_SHRAL_BASE + ((_n) * 8))
+ E1000_SHRAH_BASE = 0x0543C, /* Shared Receive Address High - RW */
+#define E1000_SHRAH(_n) (E1000_SHRAH_BASE + ((_n) * 8))
E1000_VFTA = 0x05600, /* VLAN Filter Table Array - RW Array */
E1000_WUC = 0x05800, /* Wakeup Control - RW */
E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */
@@ -782,6 +786,7 @@ struct e1000_mac_operations {
s32 (*setup_led)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
void (*config_collision_dist)(struct e1000_hw *);
+ void (*rar_set)(struct e1000_hw *, u8 *, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
};
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 4c8b0fb..ca34ebf 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -115,6 +115,7 @@
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
+#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
#define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
@@ -259,6 +260,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
@@ -672,8 +674,11 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.led_on = e1000_led_on_ich8lan;
mac->ops.led_off = e1000_led_off_ich8lan;
break;
- case e1000_pchlan:
case e1000_pch2lan:
+ mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch2lan;
+ /* fall-through */
+ case e1000_pchlan:
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
@@ -1048,6 +1053,70 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
}
/**
+ * e1000_rar_set_pch2lan - Set receive address register
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address array register at index to the address passed
+ * in by addr. For 82579, RAR[0] is the base address register that is to
+ * contain the MAC address but RAR[1-6] are reserved for manageability (ME).
+ * Use SHRA[0-3] in place of those reserved for ME.
+ **/
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[0] |
+ ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ if (index < hw->mac.rar_entry_count) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL(index - 1)) == rar_low) &&
+ (er32(SHRAH(index - 1)) == rar_high))
+ return;
+
+ e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n",
+ (index - 1), er32(FWSM));
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
* e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -4100,6 +4169,7 @@ static const struct e1000_mac_operations ich8_mac_ops = {
.setup_physical_interface= e1000_setup_copper_link_ich8lan,
/* id_led_init dependent on mac type */
.config_collision_dist = e1000e_config_collision_dist_generic,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations ich8_phy_ops = {
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c
index d832749..026e8b3 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -143,12 +143,12 @@ void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
/* Setup the receive address */
e_dbg("Programming MAC Address into RAR[0]\n");
- e1000e_rar_set(hw, hw->mac.addr, 0);
+ hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
/* Zero out the other (rar_entry_count - 1) receive addresses */
e_dbg("Clearing RAR[1-%u]\n", rar_count - 1);
for (i = 1; i < rar_count; i++)
- e1000e_rar_set(hw, mac_addr, i);
+ hw->mac.ops.rar_set(hw, mac_addr, i);
}
/**
@@ -215,13 +215,13 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
* same as the normal permanent MAC address stored by the HW into the
* RAR. Do this by mapping this address into RAR0.
*/
- e1000e_rar_set(hw, alt_mac_addr, 0);
+ hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
return 0;
}
/**
- * e1000e_rar_set - Set receive address register
+ * e1000e_rar_set_generic - Set receive address register
* @hw: pointer to the HW structure
* @addr: pointer to the receive address
* @index: receive address array register
@@ -229,7 +229,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
* Sets the receive address array register at index to the address passed
* in by addr.
**/
-void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 140fee1..c0e211b 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3209,7 +3209,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev)
netdev_for_each_uc_addr(ha, netdev) {
if (!rar_entries)
break;
- e1000e_rar_set(hw, ha->addr, rar_entries--);
+ hw->mac.ops.rar_set(hw, ha->addr, rar_entries--);
count++;
}
}
@@ -4018,6 +4018,7 @@ static int e1000_close(struct net_device *netdev)
static int e1000_set_mac(struct net_device *netdev, void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
@@ -4026,7 +4027,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len);
- e1000e_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
+ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) {
/* activate the work around */
@@ -4040,9 +4041,8 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
* are dropped. Eventually the LAA will be in RAR[0] and
* RAR[14]
*/
- e1000e_rar_set(&adapter->hw,
- adapter->hw.mac.addr,
- adapter->hw.mac.rar_entry_count - 1);
+ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr,
+ adapter->hw.mac.rar_entry_count - 1);
}
return 0;
@@ -4621,7 +4621,7 @@ link_up:
* reset from the other port. Set the appropriate LAA in RAR[0]
*/
if (e1000e_get_laa_state_82571(hw))
- e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
+ hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0);
if (adapter->flags2 & FLAG2_CHECK_PHY_HANG)
e1000e_check_82574_phy_workaround(adapter);
--
1.7.7.6
^ permalink raw reply related
* [net-next 2/8] e1000e: PHY initialization flow changes for 82577/8/9
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Bruce Allan, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
The PHY initialization flows and assorted workarounds for 82577/8/9 done
during driver load and resume from Sx should be the same yet they are not.
Combine the current flows/workarounds into a common set of functions that
are called during the different code paths.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/ich8lan.c | 247 ++++++++++++++++-----------
1 files changed, 146 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 2506ee2..4c8b0fb 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -287,25 +287,126 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
#define ew16flash(reg, val) __ew16flash(hw, (reg), (val))
#define ew32flash(reg, val) __ew32flash(hw, (reg), (val))
-static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+/**
+ * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers
+ * @hw: pointer to the HW structure
+ *
+ * Test access to the PHY registers by reading the PHY ID registers. If
+ * the PHY ID is already known (e.g. resume path) compare it with known ID,
+ * otherwise assume the read PHY ID is correct if it is valid.
+ *
+ * Assumes the sw/fw/hw semaphore is already acquired.
+ **/
+static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
{
- u32 reg;
+ u16 phy_reg;
+ u32 phy_id;
- /* Set Phy Config Counter to 50msec */
- reg = er32(FEXTNVM3);
- reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
- reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
- ew32(FEXTNVM3, reg);
-
- /* Toggle LANPHYPC Value bit */
- reg = er32(CTRL);
- reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
- reg &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, reg);
- e1e_flush();
- udelay(10);
- reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, reg);
+ hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg);
+ phy_id = (u32)(phy_reg << 16);
+ hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_reg);
+ phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+
+ if (hw->phy.id) {
+ if (hw->phy.id == phy_id)
+ return true;
+ } else {
+ if ((phy_id != 0) && (phy_id != PHY_REVISION_MASK))
+ hw->phy.id = phy_id;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
+ * @hw: pointer to the HW structure
+ *
+ * Workarounds/flow necessary for PHY initialization during driver load
+ * and resume paths.
+ **/
+static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 mac_reg, fwsm = er32(FWSM);
+ s32 ret_val;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to initialize PHY flow\n");
+ return ret_val;
+ }
+
+ /*
+ * The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ * inaccessible and resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+ */
+ switch (hw->mac.type) {
+ case e1000_pch2lan:
+ /*
+ * Gate automatic PHY configuration by hardware on
+ * non-managed 82579
+ */
+ if (!(fwsm & E1000_ICH_FWSM_FW_VALID))
+ e1000_gate_hw_phy_config_ich8lan(hw, true);
+
+ if (e1000_phy_is_accessible_pchlan(hw))
+ break;
+
+ /* fall-through */
+ case e1000_pchlan:
+ if ((hw->mac.type == e1000_pchlan) &&
+ (fwsm & E1000_ICH_FWSM_FW_VALID))
+ break;
+
+ if (hw->phy.ops.check_reset_block(hw)) {
+ e_dbg("Required LANPHYPC toggle blocked by ME\n");
+ break;
+ }
+
+ e_dbg("Toggling LANPHYPC\n");
+
+ /* Set Phy Config Counter to 50msec */
+ mac_reg = er32(FEXTNVM3);
+ mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, mac_reg);
+
+ /* Toggle LANPHYPC Value bit */
+ mac_reg = er32(CTRL);
+ mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ udelay(10);
+ mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ msleep(50);
+ break;
+ default:
+ break;
+ }
+
+ hw->phy.ops.release(hw);
+
+ /*
+ * Reset the PHY before any access to it. Doing so, ensures
+ * that the PHY is in a known good state before we read/write
+ * PHY registers. The generic reset is sufficient here,
+ * because we haven't determined the PHY type yet.
+ */
+ ret_val = e1000e_phy_hw_reset_generic(hw);
+
+ /* Ungate automatic PHY configuration on non-managed 82579 */
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+ usleep_range(10000, 20000);
+ e1000_gate_hw_phy_config_ich8lan(hw, false);
+ }
+
+ return ret_val;
}
/**
@@ -335,65 +436,34 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- if (!hw->phy.ops.check_reset_block(hw)) {
- u32 fwsm = er32(FWSM);
-
- /*
- * The MAC-PHY interconnect may still be in SMBus mode after
- * Sx->S0. If resetting the PHY is not blocked, toggle the
- * LANPHYPC Value bit to force the interconnect to PCIe mode.
- */
- e1000_toggle_lanphypc_value_ich8lan(hw);
- msleep(50);
-
- /*
- * Gate automatic PHY configuration by hardware on
- * non-managed 82579
- */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(fwsm & E1000_ICH_FWSM_FW_VALID))
- e1000_gate_hw_phy_config_ich8lan(hw, true);
-
- /*
- * Reset the PHY before any access to it. Doing so, ensures
- * that the PHY is in a known good state before we read/write
- * PHY registers. The generic reset is sufficient here,
- * because we haven't determined the PHY type yet.
- */
- ret_val = e1000e_phy_hw_reset_generic(hw);
- if (ret_val)
- return ret_val;
+ phy->id = e1000_phy_unknown;
- /* Ungate automatic PHY configuration on non-managed 82579 */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
- usleep_range(10000, 20000);
- e1000_gate_hw_phy_config_ich8lan(hw, false);
- }
- }
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val)
+ return ret_val;
- phy->id = e1000_phy_unknown;
- switch (hw->mac.type) {
- default:
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ if (phy->id == e1000_phy_unknown)
+ switch (hw->mac.type) {
+ default:
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
+ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ break;
+ /* fall-through */
+ case e1000_pch2lan:
+ /*
+ * In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
+ */
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
break;
- /* fall-through */
- case e1000_pch2lan:
- /*
- * In case the PHY needs to be in mdio slow mode,
- * set slow mode and try to get the PHY id again.
- */
- ret_val = e1000_set_mdio_slow_mode_hv(hw);
- if (ret_val)
- return ret_val;
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- break;
- }
+ }
phy->type = e1000e_get_phy_type_from_id(phy->id);
switch (phy->type) {
@@ -3736,41 +3806,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
**/
void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
- u16 phy_id1, phy_id2;
s32 ret_val;
- if ((hw->mac.type != e1000_pch2lan) ||
- hw->phy.ops.check_reset_block(hw))
+ if (hw->mac.type < e1000_pch2lan)
return;
- ret_val = hw->phy.ops.acquire(hw);
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
if (ret_val) {
- e_dbg("Failed to acquire PHY semaphore in resume\n");
+ e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val);
return;
}
-
- /* Test access to the PHY registers by reading the ID regs */
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
- if (ret_val)
- goto release;
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
- if (ret_val)
- goto release;
-
- if (hw->phy.id == ((u32)(phy_id1 << 16) |
- (u32)(phy_id2 & PHY_REVISION_MASK)))
- goto release;
-
- e1000_toggle_lanphypc_value_ich8lan(hw);
-
- hw->phy.ops.release(hw);
- msleep(50);
- e1000_phy_hw_reset(hw);
- msleep(50);
- return;
-
-release:
- hw->phy.ops.release(hw);
}
/**
--
1.7.7.6
^ permalink raw reply related
* [net-next 1/8] e1000e: workaround EEPROM configuration change on 82579
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Bruce Allan, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1335862269-28914-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
An update to the EEPROM on 82579 will extend a delay in hardware to fix an
issue with WoL not working after a G3->S5 transition which is unrelated to
the driver. However, this extended delay conflicts with nominal operation
of the device when it is initialized by the driver and after every reset
of the hardware (i.e. the driver starts configuring the device before the
hardware is done with it's own configuration work). The workaround for
when the driver is in control of the device is to tell the hardware after
every reset the configuration delay should be the original shorter one.
Some pre-existing variables are renamed generically to be re-used with
new register accesses.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/hw.h | 1 +
drivers/net/ethernet/intel/e1000e/ich8lan.c | 48 ++++++++++++++++++--------
2 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 7ca1b68..3a5acb5 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -51,6 +51,7 @@ enum e1e_registers {
E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */
E1000_FCT = 0x00030, /* Flow Control Type - RW */
E1000_VET = 0x00038, /* VLAN Ether Type - RW */
+ E1000_FEXTNVM3 = 0x0003C, /* Future Extended NVM 3 - RW */
E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */
E1000_ITR = 0x000C4, /* Interrupt Throttling Rate - RW */
E1000_ICS = 0x000C8, /* Interrupt Cause Set - WO */
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index d7fd1e8..2506ee2 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -105,6 +105,9 @@
#define E1000_FEXTNVM_SW_CONFIG 1
#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000
+
#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
@@ -286,16 +289,23 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
{
- u32 ctrl;
+ u32 reg;
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, ctrl);
+ /* Set Phy Config Counter to 50msec */
+ reg = er32(FEXTNVM3);
+ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, reg);
+
+ /* Toggle LANPHYPC Value bit */
+ reg = er32(CTRL);
+ reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ reg &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, reg);
e1e_flush();
udelay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, ctrl);
+ reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, reg);
}
/**
@@ -3071,8 +3081,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- u16 reg;
- u32 ctrl, kab;
+ u16 kum_cfg;
+ u32 ctrl, reg;
s32 ret_val;
/*
@@ -3106,12 +3116,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
}
if (hw->mac.type == e1000_pchlan) {
- /* Save the NVM K1 bit setting*/
- ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®);
+ /* Save the NVM K1 bit setting */
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg);
if (ret_val)
return ret_val;
- if (reg & E1000_NVM_K1_ENABLE)
+ if (kum_cfg & E1000_NVM_K1_ENABLE)
dev_spec->nvm_k1_enabled = true;
else
dev_spec->nvm_k1_enabled = false;
@@ -3141,6 +3151,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
/* cannot issue a flush here because it hangs the hardware */
msleep(20);
+ /* Set Phy Config Counter to 50msec */
+ if (hw->mac.type == e1000_pch2lan) {
+ reg = er32(FEXTNVM3);
+ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, reg);
+ }
+
if (!ret_val)
clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
@@ -3165,9 +3183,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(IMC, 0xffffffff);
er32(ICR);
- kab = er32(KABGTXD);
- kab |= E1000_KABGTXD_BGSQLBIAS;
- ew32(KABGTXD, kab);
+ reg = er32(KABGTXD);
+ reg |= E1000_KABGTXD_BGSQLBIAS;
+ ew32(KABGTXD, reg);
return 0;
}
--
1.7.7.6
^ permalink raw reply related
* [net-next 0/8][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-05-01 8:51 UTC (permalink / raw)
To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann, bhutchings
This series of patches contains updates for e1000e and ixgbe.
Special note that this series contains the v2 of the ixgbe
thermal data patches (patches 4-6), which have been revised based on
feedback from the community (Ben Hutchings).
The following are changes since commit 80bcb4238dd858d8ae460b62aac2f4165db58c3c:
atl1c: remove PHY polling from atl1c_change_mtu
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master
Bruce Allan (3):
e1000e: workaround EEPROM configuration change on 82579
e1000e: PHY initialization flow changes for 82577/8/9
e1000e: fix .ndo_set_rx_mode for 82579
Don Skidmore (3):
ixgbe: add support functions to access thermal data
ixgbe: add hwmon interface to export thermal data
ixgbe: add syfs interface for to export read only driver information
Greg Rose (2):
ixgbe: Deny MACVLAN requests from VFs with admin set MAC
ixgbe: Reset max_vfs to zero when user request is out of range
drivers/net/ethernet/intel/Kconfig | 8 +
drivers/net/ethernet/intel/e1000e/80003es2lan.c | 1 +
drivers/net/ethernet/intel/e1000e/82571.c | 4 +-
drivers/net/ethernet/intel/e1000e/e1000.h | 2 +-
drivers/net/ethernet/intel/e1000e/hw.h | 6 +
drivers/net/ethernet/intel/e1000e/ich8lan.c | 339 +++++++++----
drivers/net/ethernet/intel/e1000e/mac.c | 10 +-
drivers/net/ethernet/intel/e1000e/netdev.c | 12 +-
drivers/net/ethernet/intel/ixgbe/Makefile | 2 +-
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 26 +
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 2 +
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 2 +
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 169 +++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 13 +
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 13 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 6 +
drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c | 583 +++++++++++++++++++++++
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 40 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 2 +
19 files changed, 1120 insertions(+), 120 deletions(-)
create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
--
1.7.7.6
^ permalink raw reply
* Re: [PATCH 00/10 net-next] l2tp: misc fixes and add L2TPv3 IP encap over IPv6
From: James Chapman @ 2012-05-01 8:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120430.134637.1965477081443499316.davem@davemloft.net>
On 30/04/12 18:46, David Miller wrote:
> From: James Chapman <jchapman@katalix.com>
> Date: Mon, 30 Apr 2012 08:48:45 +0100
>
>> This patch series includes several L2TP fixes / cleanups and adds
>> L2TPv3 IP encapsulation support for IPv6, building on the L2TP UDP
>> IPv6 support recently added by Ben LaHaise.
>
> Series applied to net-next, thanks James.
Thanks Dave.
For some reason, I can't see the commits in the net-next tree. Are they
still in your local tree?
--
James Chapman
Katalix Systems Ltd
http://www.katalix.com
Catalysts for your Embedded Linux software development
^ permalink raw reply
* [PATCH 1/7] batman-adv: fix wrong dhcp option list browsing
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1335859266-7546-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
In is_type_dhcprequest(), while parsing a DHCP message, if the entry we found in
the option list is neither a padding nor the dhcp-type, we have to ignore it and
jump as many bytes as its length + 1. The "+ 1" byte is given by the subtype
field itself that has to be jumped too.
Reported-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Antonio Quartulli <ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
---
net/batman-adv/gateway_client.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 6f9b9b7..47f7186 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -558,10 +558,10 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
p++;
/* ...and then we jump over the data */
- if (pkt_len < *p)
+ if (pkt_len < 1 + (*p))
goto out;
- pkt_len -= *p;
- p += (*p);
+ pkt_len -= 1 + (*p);
+ p += 1 + (*p);
}
}
out:
--
1.7.9.4
^ permalink raw reply related
* pull request: batman-adv 2012-05-01
From: Antonio Quartulli @ 2012-05-01 8:00 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
Hello David,
this is the new version of my previous pull request (issued on 2012-04-29).
I'd like to see this changesin net-next/linux-3.5.
In this pull request I entirely removed the D.A.T. code, that as we were
discussing in the previous thread, needs some rewriting to avoid directly
dealing with the neigh table.
This patchset only contains fixes and cleanups.
Letme know if there is any problem!
Thank you,
Antonio
The following changes since commit 7a2a66a0ac1cf93d30869c4ecbfc71a2fda19397:
Add linux-next specific files for 20120423 (2012-04-23 16:58:43 +1000)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-for-davem
for you to fetch changes up to 969e62ad00763fed9ea28700ef7a7d97fdbfddf3:
batman-adv: split neigh_new function into generic and batman iv specific parts (2012-05-01 00:37:58 +0200)
----------------------------------------------------------------
Included changes:
* minor fixes and cleanups
* minor routing protocol API cleanups
----------------------------------------------------------------
Antonio Quartulli (1):
batman-adv: fix wrong dhcp option list browsing
Marek Lindner (6):
batman-adv: introduce is_single_hop_neigh variable to increase readability
batman-adv: introduce packet type handler array for incoming packets
batman-adv: register batman ogm receive function during protocol init
batman-adv: rename last_valid to last_seen
batman-adv: replace HZ calculations with jiffies_to_msecs()
batman-adv: split neigh_new function into generic and batman iv specific parts
net/batman-adv/bat_debugfs.c | 4 +-
net/batman-adv/bat_iv_ogm.c | 95 +++++++++++++++++++++++-------
net/batman-adv/gateway_client.c | 6 +-
net/batman-adv/hard-interface.c | 113 ------------------------------------
net/batman-adv/main.c | 122 ++++++++++++++++++++++++++++++++++++++-
net/batman-adv/main.h | 6 ++
net/batman-adv/originator.c | 50 ++++++++--------
net/batman-adv/originator.h | 6 +-
net/batman-adv/routing.c | 22 ++++---
net/batman-adv/routing.h | 4 +-
net/batman-adv/send.c | 2 +-
net/batman-adv/types.h | 11 ++--
12 files changed, 249 insertions(+), 192 deletions(-)
^ permalink raw reply
* [PATCH 7/7] batman-adv: split neigh_new function into generic and batman iv specific parts
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 40 ++++++++++++++++++++++++++++++++++------
net/batman-adv/originator.c | 27 ++++++++++-----------------
net/batman-adv/originator.h | 6 ++----
3 files changed, 46 insertions(+), 27 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 8652a75..4baabf9 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -30,6 +30,32 @@
#include "send.h"
#include "bat_algo.h"
+static struct neigh_node *bat_iv_ogm_neigh_new(struct hard_iface *hard_iface,
+ const uint8_t *neigh_addr,
+ struct orig_node *orig_node,
+ struct orig_node *orig_neigh,
+ uint32_t seqno)
+{
+ struct neigh_node *neigh_node;
+
+ neigh_node = neigh_node_new(hard_iface, neigh_addr, seqno);
+ if (!neigh_node)
+ goto out;
+
+ INIT_LIST_HEAD(&neigh_node->bonding_list);
+ spin_lock_init(&neigh_node->tq_lock);
+
+ neigh_node->orig_node = orig_neigh;
+ neigh_node->if_incoming = hard_iface;
+
+ spin_lock_bh(&orig_node->neigh_list_lock);
+ hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+ spin_unlock_bh(&orig_node->neigh_list_lock);
+
+out:
+ return neigh_node;
+}
+
static int bat_iv_ogm_iface_enable(struct hard_iface *hard_iface)
{
struct batman_ogm_packet *batman_ogm_packet;
@@ -638,8 +664,9 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv,
if (!orig_tmp)
goto unlock;
- neigh_node = create_neighbor(orig_node, orig_tmp,
- ethhdr->h_source, if_incoming);
+ neigh_node = bat_iv_ogm_neigh_new(if_incoming, ethhdr->h_source,
+ orig_node, orig_tmp,
+ batman_ogm_packet->seqno);
orig_node_free_ref(orig_tmp);
if (!neigh_node)
@@ -764,10 +791,11 @@ static int bat_iv_ogm_calc_tq(struct orig_node *orig_node,
rcu_read_unlock();
if (!neigh_node)
- neigh_node = create_neighbor(orig_neigh_node,
- orig_neigh_node,
- orig_neigh_node->orig,
- if_incoming);
+ neigh_node = bat_iv_ogm_neigh_new(if_incoming,
+ orig_neigh_node->orig,
+ orig_neigh_node,
+ orig_neigh_node,
+ batman_ogm_packet->seqno);
if (!neigh_node)
goto out;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 962636b..1bcc9c5 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -85,35 +85,28 @@ struct neigh_node *orig_node_get_router(struct orig_node *orig_node)
return router;
}
-struct neigh_node *create_neighbor(struct orig_node *orig_node,
- struct orig_node *orig_neigh_node,
- const uint8_t *neigh,
- struct hard_iface *if_incoming)
+struct neigh_node *neigh_node_new(struct hard_iface *hard_iface,
+ const uint8_t *neigh_addr, uint32_t seqno)
{
- struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+ struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct neigh_node *neigh_node;
- bat_dbg(DBG_BATMAN, bat_priv,
- "Creating new last-hop neighbor of originator\n");
-
neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
if (!neigh_node)
- return NULL;
+ goto out;
INIT_HLIST_NODE(&neigh_node->list);
- INIT_LIST_HEAD(&neigh_node->bonding_list);
- spin_lock_init(&neigh_node->tq_lock);
- memcpy(neigh_node->addr, neigh, ETH_ALEN);
- neigh_node->orig_node = orig_neigh_node;
- neigh_node->if_incoming = if_incoming;
+ memcpy(neigh_node->addr, neigh_addr, ETH_ALEN);
/* extra reference for return */
atomic_set(&neigh_node->refcount, 2);
- spin_lock_bh(&orig_node->neigh_list_lock);
- hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
- spin_unlock_bh(&orig_node->neigh_list_lock);
+ bat_dbg(DBG_BATMAN, bat_priv,
+ "Creating new neighbor %pM, initial seqno %d\n",
+ neigh_addr, seqno);
+
+out:
return neigh_node;
}
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 3fe2eda..64c5d94 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -29,10 +29,8 @@ void originator_free(struct bat_priv *bat_priv);
void purge_orig_ref(struct bat_priv *bat_priv);
void orig_node_free_ref(struct orig_node *orig_node);
struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr);
-struct neigh_node *create_neighbor(struct orig_node *orig_node,
- struct orig_node *orig_neigh_node,
- const uint8_t *neigh,
- struct hard_iface *if_incoming);
+struct neigh_node *neigh_node_new(struct hard_iface *hard_iface,
+ const uint8_t *neigh_addr, uint32_t seqno);
void neigh_node_free_ref(struct neigh_node *neigh_node);
struct neigh_node *orig_node_get_router(struct orig_node *orig_node);
int orig_seq_print_text(struct seq_file *seq, void *offset);
--
1.7.9.4
^ permalink raw reply related
* [PATCH 5/7] batman-adv: rename last_valid to last_seen
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 8 ++++----
net/batman-adv/originator.c | 16 ++++++++--------
net/batman-adv/types.h | 8 ++++----
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e0aaf8c..8652a75 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -651,7 +651,7 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv,
rcu_read_unlock();
orig_node->flags = batman_ogm_packet->flags;
- neigh_node->last_valid = jiffies;
+ neigh_node->last_seen = jiffies;
spin_lock_bh(&neigh_node->tq_lock);
ring_buffer_set(neigh_node->tq_recv,
@@ -772,11 +772,11 @@ static int bat_iv_ogm_calc_tq(struct orig_node *orig_node,
if (!neigh_node)
goto out;
- /* if orig_node is direct neighbor update neigh_node last_valid */
+ /* if orig_node is direct neighbor update neigh_node last_seen */
if (orig_node == orig_neigh_node)
- neigh_node->last_valid = jiffies;
+ neigh_node->last_seen = jiffies;
- orig_node->last_valid = jiffies;
+ orig_node->last_seen = jiffies;
/* find packet count of corresponding one hop neighbor */
spin_lock_bh(&orig_node->ogm_cnt_lock);
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ce49698..21c1f83 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -283,7 +283,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
hlist_for_each_entry_safe(neigh_node, node, node_tmp,
&orig_node->neigh_list, list) {
- if ((has_timed_out(neigh_node->last_valid, PURGE_TIMEOUT)) ||
+ if ((has_timed_out(neigh_node->last_seen, PURGE_TIMEOUT)) ||
(neigh_node->if_incoming->if_status == IF_INACTIVE) ||
(neigh_node->if_incoming->if_status == IF_NOT_IN_USE) ||
(neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
@@ -300,9 +300,9 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
neigh_node->if_incoming->net_dev->name);
else
bat_dbg(DBG_BATMAN, bat_priv,
- "neighbor timeout: originator %pM, neighbor: %pM, last_valid: %lu\n",
+ "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %lu\n",
orig_node->orig, neigh_node->addr,
- (neigh_node->last_valid / HZ));
+ (neigh_node->last_seen / HZ));
neigh_purged = true;
@@ -325,10 +325,10 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
{
struct neigh_node *best_neigh_node;
- if (has_timed_out(orig_node->last_valid, 2 * PURGE_TIMEOUT)) {
+ if (has_timed_out(orig_node->last_seen, 2 * PURGE_TIMEOUT)) {
bat_dbg(DBG_BATMAN, bat_priv,
- "Originator timeout: originator %pM, last_valid %lu\n",
- orig_node->orig, (orig_node->last_valid / HZ));
+ "Originator timeout: originator %pM, last_seen %lu\n",
+ orig_node->orig, (orig_node->last_seen / HZ));
return true;
} else {
if (purge_orig_neighbors(bat_priv, orig_node,
@@ -446,9 +446,9 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
goto next;
last_seen_secs = jiffies_to_msecs(jiffies -
- orig_node->last_valid) / 1000;
+ orig_node->last_seen) / 1000;
last_seen_msecs = jiffies_to_msecs(jiffies -
- orig_node->last_valid) % 1000;
+ orig_node->last_seen) % 1000;
seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:",
orig_node->orig, last_seen_secs,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 50e1895..9fa8b73 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -52,7 +52,7 @@ struct hard_iface {
/**
* orig_node - structure for orig_list maintaining nodes of mesh
* @primary_addr: hosts primary interface address
- * @last_valid: when last packet from this node was received
+ * @last_seen: when last packet from this node was received
* @bcast_seqno_reset: time when the broadcast seqno window was reset
* @batman_seqno_reset: time when the batman seqno window was reset
* @gw_flags: flags related to gateway class
@@ -70,7 +70,7 @@ struct orig_node {
struct neigh_node __rcu *router; /* rcu protected pointer */
unsigned long *bcast_own;
uint8_t *bcast_own_sum;
- unsigned long last_valid;
+ unsigned long last_seen;
unsigned long bcast_seqno_reset;
unsigned long batman_seqno_reset;
uint8_t gw_flags;
@@ -120,7 +120,7 @@ struct gw_node {
/**
* neigh_node
- * @last_valid: when last packet via this neighbor was received
+ * @last_seen: when last packet via this neighbor was received
*/
struct neigh_node {
struct hlist_node list;
@@ -131,7 +131,7 @@ struct neigh_node {
uint8_t tq_avg;
uint8_t last_ttl;
struct list_head bonding_list;
- unsigned long last_valid;
+ unsigned long last_seen;
DECLARE_BITMAP(real_bits, TQ_LOCAL_WINDOW_SIZE);
atomic_t refcount;
struct rcu_head rcu;
--
1.7.9.4
^ permalink raw reply related
* [PATCH 6/7] batman-adv: replace HZ calculations with jiffies_to_msecs()
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_debugfs.c | 4 ++--
net/batman-adv/originator.c | 15 ++++++++++-----
net/batman-adv/send.c | 2 +-
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index 916380c..3b588f8 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -83,8 +83,8 @@ int debug_log(struct bat_priv *bat_priv, const char *fmt, ...)
va_start(args, fmt);
vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
- fdebug_log(bat_priv->debug_log, "[%10lu] %s",
- (jiffies / HZ), tmp_log_buf);
+ fdebug_log(bat_priv->debug_log, "[%10u] %s",
+ jiffies_to_msecs(jiffies), tmp_log_buf);
va_end(args);
return 0;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 21c1f83..962636b 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -35,7 +35,8 @@ static void purge_orig(struct work_struct *work);
static void start_purge_timer(struct bat_priv *bat_priv)
{
INIT_DELAYED_WORK(&bat_priv->orig_work, purge_orig);
- queue_delayed_work(bat_event_workqueue, &bat_priv->orig_work, 1 * HZ);
+ queue_delayed_work(bat_event_workqueue,
+ &bat_priv->orig_work, msecs_to_jiffies(1000));
}
/* returns 1 if they are the same originator */
@@ -274,6 +275,7 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
struct hlist_node *node, *node_tmp;
struct neigh_node *neigh_node;
bool neigh_purged = false;
+ unsigned long last_seen;
*best_neigh_node = NULL;
@@ -288,6 +290,8 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
(neigh_node->if_incoming->if_status == IF_NOT_IN_USE) ||
(neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
+ last_seen = neigh_node->last_seen;
+
if ((neigh_node->if_incoming->if_status ==
IF_INACTIVE) ||
(neigh_node->if_incoming->if_status ==
@@ -300,9 +304,9 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
neigh_node->if_incoming->net_dev->name);
else
bat_dbg(DBG_BATMAN, bat_priv,
- "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %lu\n",
+ "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n",
orig_node->orig, neigh_node->addr,
- (neigh_node->last_seen / HZ));
+ jiffies_to_msecs(last_seen));
neigh_purged = true;
@@ -327,8 +331,9 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
if (has_timed_out(orig_node->last_seen, 2 * PURGE_TIMEOUT)) {
bat_dbg(DBG_BATMAN, bat_priv,
- "Originator timeout: originator %pM, last_seen %lu\n",
- orig_node->orig, (orig_node->last_seen / HZ));
+ "Originator timeout: originator %pM, last_seen %u\n",
+ orig_node->orig,
+ jiffies_to_msecs(orig_node->last_seen));
return true;
} else {
if (purge_orig_neighbors(bat_priv, orig_node,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 7c66b61..8e74d97 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -292,7 +292,7 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
/* if we still have some more bcasts to send */
if (forw_packet->num_packets < 3) {
_add_bcast_packet_to_list(bat_priv, forw_packet,
- ((5 * HZ) / 1000));
+ msecs_to_jiffies(5));
return;
}
--
1.7.9.4
^ permalink raw reply related
* [PATCH 4/7] batman-adv: register batman ogm receive function during protocol init
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
The B.A.T.M.A.N. IV OGM receive function still was hard-coded although
it is a routing protocol specific function. This patch takes advantage
of the dynamic packet handler registration to remove the hard-coded
function calls.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 31 +++++++++++++++++++++++++++----
net/batman-adv/main.c | 5 +----
net/batman-adv/routing.c | 22 ++++++++++------------
net/batman-adv/routing.h | 4 +++-
net/batman-adv/types.h | 3 ---
5 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index cd8f473..e0aaf8c 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1155,13 +1155,18 @@ out:
orig_node_free_ref(orig_node);
}
-static void bat_iv_ogm_receive(struct hard_iface *if_incoming,
- struct sk_buff *skb)
+static int bat_iv_ogm_receive(struct sk_buff *skb,
+ struct hard_iface *if_incoming)
{
struct batman_ogm_packet *batman_ogm_packet;
struct ethhdr *ethhdr;
int buff_pos = 0, packet_len;
unsigned char *tt_buff, *packet_buff;
+ bool ret;
+
+ ret = check_management_packet(skb, if_incoming, BATMAN_OGM_HLEN);
+ if (!ret)
+ return NET_RX_DROP;
packet_len = skb_headlen(skb);
ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -1187,6 +1192,9 @@ static void bat_iv_ogm_receive(struct hard_iface *if_incoming,
(packet_buff + buff_pos);
} while (bat_iv_ogm_aggr_packet(buff_pos, packet_len,
batman_ogm_packet->tt_num_changes));
+
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
}
static struct bat_algo_ops batman_iv __read_mostly = {
@@ -1197,10 +1205,25 @@ static struct bat_algo_ops batman_iv __read_mostly = {
.bat_ogm_update_mac = bat_iv_ogm_update_mac,
.bat_ogm_schedule = bat_iv_ogm_schedule,
.bat_ogm_emit = bat_iv_ogm_emit,
- .bat_ogm_receive = bat_iv_ogm_receive,
};
int __init bat_iv_init(void)
{
- return bat_algo_register(&batman_iv);
+ int ret;
+
+ /* batman originator packet */
+ ret = recv_handler_register(BAT_IV_OGM, bat_iv_ogm_receive);
+ if (ret < 0)
+ goto out;
+
+ ret = bat_algo_register(&batman_iv);
+ if (ret < 0)
+ goto handler_unregister;
+
+ goto out;
+
+handler_unregister:
+ recv_handler_unregister(BAT_IV_OGM);
+out:
+ return ret;
}
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index d19b935..f80c447 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -266,8 +266,6 @@ static void recv_handler_init(void)
for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
recv_packet_handler[i] = recv_unhandled_packet;
- /* batman originator packet */
- recv_packet_handler[BAT_IV_OGM] = recv_bat_ogm_packet;
/* batman icmp packet */
recv_packet_handler[BAT_ICMP] = recv_icmp_packet;
/* unicast packet */
@@ -334,8 +332,7 @@ int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
!bat_algo_ops->bat_primary_iface_set ||
!bat_algo_ops->bat_ogm_update_mac ||
!bat_algo_ops->bat_ogm_schedule ||
- !bat_algo_ops->bat_ogm_emit ||
- !bat_algo_ops->bat_ogm_receive) {
+ !bat_algo_ops->bat_ogm_emit) {
pr_info("Routing algo '%s' does not implement required ops\n",
bat_algo_ops->name);
goto out;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index ff56086..7ed9d8f 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -248,37 +248,35 @@ int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff,
return 0;
}
-int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
+bool check_management_packet(struct sk_buff *skb,
+ struct hard_iface *hard_iface,
+ int header_len)
{
- struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */
- if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_HLEN)))
- return NET_RX_DROP;
+ if (unlikely(!pskb_may_pull(skb, header_len)))
+ return false;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with broadcast indication but unicast recipient */
if (!is_broadcast_ether_addr(ethhdr->h_dest))
- return NET_RX_DROP;
+ return false;
/* packet with broadcast sender address */
if (is_broadcast_ether_addr(ethhdr->h_source))
- return NET_RX_DROP;
+ return false;
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, 0) < 0)
- return NET_RX_DROP;
+ return false;
/* keep skb linear */
if (skb_linearize(skb) < 0)
- return NET_RX_DROP;
+ return false;
- bat_priv->bat_algo_ops->bat_ogm_receive(hard_iface, skb);
-
- kfree_skb(skb);
- return NET_RX_SUCCESS;
+ return true;
}
static int recv_my_icmp_packet(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 3d729cb..d6bbbeb 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -23,6 +23,9 @@
#define _NET_BATMAN_ADV_ROUTING_H_
void slide_own_bcast_window(struct hard_iface *hard_iface);
+bool check_management_packet(struct sk_buff *skb,
+ struct hard_iface *hard_iface,
+ int header_len);
void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node,
struct neigh_node *neigh_node);
int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
@@ -30,7 +33,6 @@ int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
-int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if);
int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if);
struct neigh_node *find_router(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 2f4848b..50e1895 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -390,9 +390,6 @@ struct bat_algo_ops {
int tt_num_changes);
/* send scheduled OGM */
void (*bat_ogm_emit)(struct forw_packet *forw_packet);
- /* receive incoming OGM */
- void (*bat_ogm_receive)(struct hard_iface *if_incoming,
- struct sk_buff *skb);
};
#endif /* _NET_BATMAN_ADV_TYPES_H_ */
--
1.7.9.4
^ permalink raw reply related
* [PATCH 2/7] batman-adv: introduce is_single_hop_neigh variable to increase readability
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 8b2db2e..cd8f473 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -480,7 +480,8 @@ static void bat_iv_ogm_queue_add(struct bat_priv *bat_priv,
static void bat_iv_ogm_forward(struct orig_node *orig_node,
const struct ethhdr *ethhdr,
struct batman_ogm_packet *batman_ogm_packet,
- int directlink, struct hard_iface *if_incoming)
+ bool is_single_hop_neigh,
+ struct hard_iface *if_incoming)
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct neigh_node *router;
@@ -533,7 +534,7 @@ static void bat_iv_ogm_forward(struct orig_node *orig_node,
/* switch of primaries first hop flag when forwarding */
batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP;
- if (directlink)
+ if (is_single_hop_neigh)
batman_ogm_packet->flags |= DIRECTLINK;
else
batman_ogm_packet->flags &= ~DIRECTLINK;
@@ -918,7 +919,8 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
struct neigh_node *orig_neigh_router = NULL;
int has_directlink_flag;
int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
- int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
+ int is_broadcast = 0, is_bidirectional;
+ bool is_single_hop_neigh = false;
int is_duplicate;
uint32_t if_incoming_seqno;
@@ -942,8 +944,8 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
- is_single_hop_neigh = (compare_eth(ethhdr->h_source,
- batman_ogm_packet->orig) ? 1 : 0);
+ if (compare_eth(ethhdr->h_source, batman_ogm_packet->orig))
+ is_single_hop_neigh = true;
bat_dbg(DBG_BATMAN, bat_priv,
"Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
@@ -1114,7 +1116,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
/* mark direct link on incoming interface */
bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
- 1, if_incoming);
+ is_single_hop_neigh, if_incoming);
bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
@@ -1137,7 +1139,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: rebroadcast originator packet\n");
bat_iv_ogm_forward(orig_node, ethhdr, batman_ogm_packet,
- 0, if_incoming);
+ is_single_hop_neigh, if_incoming);
out_neigh:
if ((orig_neigh_node) && (!is_single_hop_neigh))
--
1.7.9.4
^ permalink raw reply related
* [PATCH 3/7] batman-adv: introduce packet type handler array for incoming packets
From: Antonio Quartulli @ 2012-05-01 8:01 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1335859266-7546-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
The packet handler array replaces the growing switch statement, thus
dealing with incoming packets in a more efficient way. It also adds
to possibility to register packet handlers on the fly.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/hard-interface.c | 113 ------------------------------------
net/batman-adv/main.c | 121 +++++++++++++++++++++++++++++++++++++++
net/batman-adv/main.h | 6 ++
3 files changed, 127 insertions(+), 113 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 47c79d7..95f869c 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -32,12 +32,6 @@
#include <linux/if_arp.h>
-
-static int batman_skb_recv(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *ptype,
- struct net_device *orig_dev);
-
void hardif_free_rcu(struct rcu_head *rcu)
{
struct hard_iface *hard_iface;
@@ -551,113 +545,6 @@ out:
return NOTIFY_DONE;
}
-/* incoming packets with the batman ethertype received on any active hard
- * interface */
-static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype,
- struct net_device *orig_dev)
-{
- struct bat_priv *bat_priv;
- struct batman_ogm_packet *batman_ogm_packet;
- struct hard_iface *hard_iface;
- int ret;
-
- hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
- skb = skb_share_check(skb, GFP_ATOMIC);
-
- /* skb was released by skb_share_check() */
- if (!skb)
- goto err_out;
-
- /* packet should hold at least type and version */
- if (unlikely(!pskb_may_pull(skb, 2)))
- goto err_free;
-
- /* expect a valid ethernet header here. */
- if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
- goto err_free;
-
- if (!hard_iface->soft_iface)
- goto err_free;
-
- bat_priv = netdev_priv(hard_iface->soft_iface);
-
- if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
- goto err_free;
-
- /* discard frames on not active interfaces */
- if (hard_iface->if_status != IF_ACTIVE)
- goto err_free;
-
- batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
-
- if (batman_ogm_packet->header.version != COMPAT_VERSION) {
- bat_dbg(DBG_BATMAN, bat_priv,
- "Drop packet: incompatible batman version (%i)\n",
- batman_ogm_packet->header.version);
- goto err_free;
- }
-
- /* all receive handlers return whether they received or reused
- * the supplied skb. if not, we have to free the skb. */
-
- switch (batman_ogm_packet->header.packet_type) {
- /* batman originator packet */
- case BAT_IV_OGM:
- ret = recv_bat_ogm_packet(skb, hard_iface);
- break;
-
- /* batman icmp packet */
- case BAT_ICMP:
- ret = recv_icmp_packet(skb, hard_iface);
- break;
-
- /* unicast packet */
- case BAT_UNICAST:
- ret = recv_unicast_packet(skb, hard_iface);
- break;
-
- /* fragmented unicast packet */
- case BAT_UNICAST_FRAG:
- ret = recv_ucast_frag_packet(skb, hard_iface);
- break;
-
- /* broadcast packet */
- case BAT_BCAST:
- ret = recv_bcast_packet(skb, hard_iface);
- break;
-
- /* vis packet */
- case BAT_VIS:
- ret = recv_vis_packet(skb, hard_iface);
- break;
- /* Translation table query (request or response) */
- case BAT_TT_QUERY:
- ret = recv_tt_query(skb, hard_iface);
- break;
- /* Roaming advertisement */
- case BAT_ROAM_ADV:
- ret = recv_roam_adv(skb, hard_iface);
- break;
- default:
- ret = NET_RX_DROP;
- }
-
- if (ret == NET_RX_DROP)
- kfree_skb(skb);
-
- /* return NET_RX_SUCCESS in any case as we
- * most probably dropped the packet for
- * routing-logical reasons. */
-
- return NET_RX_SUCCESS;
-
-err_free:
- kfree_skb(skb);
-err_out:
- return NET_RX_DROP;
-}
-
/* This function returns true if the interface represented by ifindex is a
* 802.11 wireless device */
bool is_wifi_iface(int ifindex)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 7913272..d19b935 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -39,6 +39,7 @@
/* List manipulations on hardif_list have to be rtnl_lock()'ed,
* list traversals just rcu-locked */
struct list_head hardif_list;
+static int (*recv_packet_handler[256])(struct sk_buff *, struct hard_iface *);
char bat_routing_algo[20] = "BATMAN IV";
static struct hlist_head bat_algo_list;
@@ -46,11 +47,15 @@ unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct workqueue_struct *bat_event_workqueue;
+static void recv_handler_init(void);
+
static int __init batman_init(void)
{
INIT_LIST_HEAD(&hardif_list);
INIT_HLIST_HEAD(&bat_algo_list);
+ recv_handler_init();
+
bat_iv_init();
/* the name should not be longer than 10 chars - see
@@ -179,6 +184,122 @@ int is_my_mac(const uint8_t *addr)
return 0;
}
+static int recv_unhandled_packet(struct sk_buff *skb,
+ struct hard_iface *recv_if)
+{
+ return NET_RX_DROP;
+}
+
+/* incoming packets with the batman ethertype received on any active hard
+ * interface
+ */
+int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype, struct net_device *orig_dev)
+{
+ struct bat_priv *bat_priv;
+ struct batman_ogm_packet *batman_ogm_packet;
+ struct hard_iface *hard_iface;
+ uint8_t idx;
+ int ret;
+
+ hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
+ skb = skb_share_check(skb, GFP_ATOMIC);
+
+ /* skb was released by skb_share_check() */
+ if (!skb)
+ goto err_out;
+
+ /* packet should hold at least type and version */
+ if (unlikely(!pskb_may_pull(skb, 2)))
+ goto err_free;
+
+ /* expect a valid ethernet header here. */
+ if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
+ goto err_free;
+
+ if (!hard_iface->soft_iface)
+ goto err_free;
+
+ bat_priv = netdev_priv(hard_iface->soft_iface);
+
+ if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
+ goto err_free;
+
+ /* discard frames on not active interfaces */
+ if (hard_iface->if_status != IF_ACTIVE)
+ goto err_free;
+
+ batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
+
+ if (batman_ogm_packet->header.version != COMPAT_VERSION) {
+ bat_dbg(DBG_BATMAN, bat_priv,
+ "Drop packet: incompatible batman version (%i)\n",
+ batman_ogm_packet->header.version);
+ goto err_free;
+ }
+
+ /* all receive handlers return whether they received or reused
+ * the supplied skb. if not, we have to free the skb.
+ */
+ idx = batman_ogm_packet->header.packet_type;
+ ret = (*recv_packet_handler[idx])(skb, hard_iface);
+
+ if (ret == NET_RX_DROP)
+ kfree_skb(skb);
+
+ /* return NET_RX_SUCCESS in any case as we
+ * most probably dropped the packet for
+ * routing-logical reasons.
+ */
+ return NET_RX_SUCCESS;
+
+err_free:
+ kfree_skb(skb);
+err_out:
+ return NET_RX_DROP;
+}
+
+static void recv_handler_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(recv_packet_handler); i++)
+ recv_packet_handler[i] = recv_unhandled_packet;
+
+ /* batman originator packet */
+ recv_packet_handler[BAT_IV_OGM] = recv_bat_ogm_packet;
+ /* batman icmp packet */
+ recv_packet_handler[BAT_ICMP] = recv_icmp_packet;
+ /* unicast packet */
+ recv_packet_handler[BAT_UNICAST] = recv_unicast_packet;
+ /* fragmented unicast packet */
+ recv_packet_handler[BAT_UNICAST_FRAG] = recv_ucast_frag_packet;
+ /* broadcast packet */
+ recv_packet_handler[BAT_BCAST] = recv_bcast_packet;
+ /* vis packet */
+ recv_packet_handler[BAT_VIS] = recv_vis_packet;
+ /* Translation table query (request or response) */
+ recv_packet_handler[BAT_TT_QUERY] = recv_tt_query;
+ /* Roaming advertisement */
+ recv_packet_handler[BAT_ROAM_ADV] = recv_roam_adv;
+}
+
+int recv_handler_register(uint8_t packet_type,
+ int (*recv_handler)(struct sk_buff *,
+ struct hard_iface *))
+{
+ if (recv_packet_handler[packet_type] != &recv_unhandled_packet)
+ return -EBUSY;
+
+ recv_packet_handler[packet_type] = recv_handler;
+ return 0;
+}
+
+void recv_handler_unregister(uint8_t packet_type)
+{
+ recv_packet_handler[packet_type] = recv_unhandled_packet;
+}
+
static struct bat_algo_ops *bat_algo_get(char *name)
{
struct bat_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index d9832ac..fd83acd 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -155,6 +155,12 @@ void mesh_free(struct net_device *soft_iface);
void inc_module_count(void);
void dec_module_count(void);
int is_my_mac(const uint8_t *addr);
+int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype, struct net_device *orig_dev);
+int recv_handler_register(uint8_t packet_type,
+ int (*recv_handler)(struct sk_buff *,
+ struct hard_iface *));
+void recv_handler_unregister(uint8_t packet_type);
int bat_algo_register(struct bat_algo_ops *bat_algo_ops);
int bat_algo_select(struct bat_priv *bat_priv, char *name);
int bat_algo_seq_print_text(struct seq_file *seq, void *offset);
--
1.7.9.4
^ permalink raw reply related
* [PATCH] net: fix two typos in skbuff.h
From: Eric Dumazet @ 2012-05-01 7:29 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
fix kernel doc typos in function names
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/skbuff.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 775292a..111f26b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1020,7 +1020,7 @@ static inline void skb_queue_splice(const struct sk_buff_head *list,
}
/**
- * skb_queue_splice - join two skb lists and reinitialise the emptied list
+ * skb_queue_splice_init - join two skb lists and reinitialise the emptied list
* @list: the new list to add
* @head: the place to add it in the first list
*
@@ -1051,7 +1051,7 @@ static inline void skb_queue_splice_tail(const struct sk_buff_head *list,
}
/**
- * skb_queue_splice_tail - join two skb lists and reinitialise the emptied list
+ * skb_queue_splice_tail_init - join two skb lists and reinitialise the emptied list
* @list: the new list to add
* @head: the place to add it in the first list
*
^ permalink raw reply related
* Re: [PATCH net-next] bnx2x: remove some bloat
From: Eilon Greenstein @ 2012-05-01 6:57 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, netdev, Neal Cardwell, Tom Herbert,
Maciej Żenczykowski, Jeff Kirsher, Ben Hutchings,
Matt Carlson, Michael Chan, Herbert Xu
In-Reply-To: <1335598761.2900.49.camel@edumazet-glaptop>
On Sat, 2012-04-28 at 09:39 +0200, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> Before doing skb->head_frag work on bnx2x driver, I found too much stuff
> was inlined in bnx2x/bnx2x_cmn.h for no good reason and made my work not
> very easy.
>
> Move some big functions out of this include file to the respective .c
> file.
>
> A lot of inline keywords are not needed at all in this huge driver.
>
> text data bss dec hex filename
> 490083 1270 56 491409 77f91 bnx2x/bnx2x.ko.before
> 484206 1270 56 485532 7689c bnx2x/bnx2x.ko
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Eilon Greenstein <eilong@broadcom.com>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: Maciej Żenczykowski <maze@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> Cc: Tom Herbert <therbert@google.com>
> Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> Cc: Ben Hutchings <bhutchings@solarflare.com>
> Cc: Matt Carlson <mcarlson@broadcom.com>
> Cc: Michael Chan <mchan@broadcom.com>
Acked-by: Eilon Greenstein <eilong@broadcom.com>
Thanks Eric - it makes sense.
^ permalink raw reply
* Re: [PATCH net-next] net: add a prefetch in socket backlog processing
From: Eric Dumazet @ 2012-05-01 6:42 UTC (permalink / raw)
To: Joe Perches; +Cc: David Miller, netdev
In-Reply-To: <1335854091.11396.21.camel@edumazet-glaptop>
On Tue, 2012-05-01 at 08:34 +0200, Eric Dumazet wrote:
> Basically this patch avoids one memory cache miss per iteration.
>
This patch was the easy part.
I am now working on refining __skb_dequeue() API to avoid the cache line
miss when we perform the __skb_unlink() and allow a prefetch(next) as
well, to speedup process_backlog().
^ permalink raw reply
* Re: [PATCH 3/4 v2 net-next] net: make GRO aware of skb->head_frag
From: Eric Dumazet @ 2012-05-01 6:39 UTC (permalink / raw)
To: Alexander Duyck
Cc: Alexander Duyck, David Miller, netdev, Neal Cardwell, Tom Herbert,
Jeff Kirsher, Michael Chan, Matt Carlson, Herbert Xu,
Ben Hutchings, Ilpo Järvinen, Maciej Żenczykowski
In-Reply-To: <CAKgT0UdeVvJe6k5OitkKgujSw3SQSOvtQ84KrPch8xdd=5ub1A@mail.gmail.com>
On Mon, 2012-04-30 at 22:33 -0700, Alexander Duyck wrote:
> The question I had was more specific to GRO. As long as we have
> skb->users == 1 and the skb isn't cloned we should be fine. It just
> hadn't occurred to me before that napi_gro_receive had the extra
> requirement that the skb couldn't be cloned.
>
OK
By the way, even if skb was cloned, we would be allowed to steal
skb->head.
When we clone an oskb we :
1) allocate a struct nskb sk_buff (or use the shadow in case of TCP)
2) increment dataref
3) link skb->head
After cloning() nskb->users == 1, and oskb->users is unchanged
I believe you are referring to skb_get(oskb), that ones increment
oskb->users and skb_shared(oskb) then returns true.
^ permalink raw reply
* Re: [PATCH net-next] net: add a prefetch in socket backlog processing
From: Eric Dumazet @ 2012-05-01 6:34 UTC (permalink / raw)
To: Joe Perches; +Cc: David Miller, netdev
In-Reply-To: <1335842663.26217.10.camel@joe2Laptop>
On Mon, 2012-04-30 at 20:24 -0700, Joe Perches wrote:
> On Tue, 2012-05-01 at 04:07 +0200, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> >
> > TCP or UDP stacks have big enough latencies that prefetching next
> > pointer is worth it.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > ---
> > net/core/sock.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/net/core/sock.c b/net/core/sock.c
> > index 836bca6..1a88351 100644
> > --- a/net/core/sock.c
> > +++ b/net/core/sock.c
> > @@ -1700,6 +1700,7 @@ static void __release_sock(struct sock *sk)
> > do {
> > struct sk_buff *next = skb->next;
> >
> > + prefetch(next);
> > WARN_ON_ONCE(skb_dst_is_noref(skb));
> > skb->next = NULL;
> > sk_backlog_rcv(sk, skb);
>
> Hi Eric.
>
> Why should next be "prefetch"ed when
> two lines below it's set to null and
> the only use is as a pointer not as
> an apparently undereferenced pointer?
>
>
Thats because you have no idea of what is happening ?
next points to the next skb in list (after this skb)
prefetch(next) instructs CPU to preload its cache with the memory
content of first cache line of next skb (it contains its own ->next
pointer)
After prefetch(next), we clear skb->next before continuing, but we later
will need the memory we preloaded in cpu cache at next iteration.
Basically this patch avoids one memory cache miss per iteration.
^ permalink raw reply
* Re: [PATCH 3/4 v2 net-next] net: make GRO aware of skb->head_frag
From: Alexander Duyck @ 2012-05-01 5:33 UTC (permalink / raw)
To: Eric Dumazet
Cc: Alexander Duyck, David Miller, netdev, Neal Cardwell, Tom Herbert,
Jeff Kirsher, Michael Chan, Matt Carlson, Herbert Xu,
Ben Hutchings, Ilpo Järvinen, Maciej Żenczykowski
In-Reply-To: <1335835677.11396.5.camel@edumazet-glaptop>
On Mon, Apr 30, 2012 at 6:27 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2012-04-30 at 16:36 -0700, Alexander Duyck wrote:
>> On 04/30/2012 11:10 AM, Eric Dumazet wrote:
>> > From: Eric Dumazet <edumazet@google.com>
>> >
>> > GRO can check if skb to be merged has its skb->head mapped to a page
>> > fragment, instead of a kmalloc() area.
>> >
>> > We 'upgrade' skb->head as a fragment in itself
>> >
>> > This avoids the frag_list fallback, and permits to build true GRO skb
>> > (one sk_buff and up to 16 fragments), using less memory.
>> >
>> > This reduces number of cache misses when user makes its copy, since a
>> > single sk_buff is fetched.
>> >
>> > This is a followup of patch "net: allow skb->head to be a page fragment"
>> >
[...]
>> > diff --git a/net/core/skbuff.c b/net/core/skbuff.c
>> > index effa75d..2ad1ee7 100644
>> > --- a/net/core/skbuff.c
>> > +++ b/net/core/skbuff.c
>> > @@ -69,7 +69,7 @@
>> > #include <trace/events/skb.h>
>> > #include <linux/highmem.h>
>> >
>> > -static struct kmem_cache *skbuff_head_cache __read_mostly;
>> > +struct kmem_cache *skbuff_head_cache __read_mostly;
>> > static struct kmem_cache *skbuff_fclone_cache __read_mostly;
>> >
>> > static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
>> > @@ -2901,6 +2901,31 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
>> >
>> > NAPI_GRO_CB(skb)->free = 1;
>> > goto done;
>> > + } else if (skb->head_frag) {
>> > + int nr_frags = pinfo->nr_frags;
>> > + skb_frag_t *frag = pinfo->frags + nr_frags;
>> > + struct page *page = virt_to_head_page(skb->head);
>> > + unsigned int first_size = headlen - offset;
>> > + unsigned int first_offset;
>> > +
>> > + if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS)
>> > + return -E2BIG;
>> > +
>> > + first_offset = skb->data -
>> > + (unsigned char *)page_address(page) +
>> > + offset;
>> > +
>> > + pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags;
>> > +
>> > + frag->page.p = page;
>> > + frag->page_offset = first_offset;
>> > + skb_frag_size_set(frag, first_size);
>> > +
>> > + memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags);
>> > + /* We dont need to clear skbinfo->nr_frags here */
>> > +
>> > + NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
>> > + goto done;
>> > } else if (skb_gro_len(p) != pinfo->gso_size)
>> > return -E2BIG;
>> >
>> >
>> >
>> Maybe I missed something, but shouldn't you be checking skb->cloned, and
>> skb_shinfo()->dataref before you can consider just dropping the
>> sk_buff? It seems like if you are sharing the frag with a clone you
>> would have to retain the skb->head so that you can track the dataref.
>> Otherwise you will likely cause issues because the stack could end up
>> freeing the sk_buff, or the GRO frame will be capable of calling
>> put_page and freeing the page out from under the clone.
>>
>
> Is it a general question, or specific to this patch ?
>
> If its a general problem, we already check dataref where appropriate.
> Fact that skb->head is a kmalloc() or frag doesnt matter.
>
> If specific to GRO, see my first answer. GRO owns each skb.
>
> adding a BUG() would make no sense here.
The question I had was more specific to GRO. As long as we have
skb->users == 1 and the skb isn't cloned we should be fine. It just
hadn't occurred to me before that napi_gro_receive had the extra
requirement that the skb couldn't be cloned.
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH net-next] net: add a prefetch in socket backlog processing
From: Joe Perches @ 2012-05-01 3:24 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1335838029.11396.12.camel@edumazet-glaptop>
On Tue, 2012-05-01 at 04:07 +0200, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> TCP or UDP stacks have big enough latencies that prefetching next
> pointer is worth it.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
> net/core/sock.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 836bca6..1a88351 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1700,6 +1700,7 @@ static void __release_sock(struct sock *sk)
> do {
> struct sk_buff *next = skb->next;
>
> + prefetch(next);
> WARN_ON_ONCE(skb_dst_is_noref(skb));
> skb->next = NULL;
> sk_backlog_rcv(sk, skb);
Hi Eric.
Why should next be "prefetch"ed when
two lines below it's set to null and
the only use is as a pointer not as
an apparently undereferenced pointer?
^ permalink raw reply
* [PATCH net-next] net: skb_peek()/skb_peek_tail() cleanups
From: Eric Dumazet @ 2012-05-01 2:31 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
remove useless casts and rename variables for less confusion.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/skbuff.h | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2c75e98..988fc49 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -883,10 +883,11 @@ static inline struct sk_buff *skb_unshare(struct sk_buff *skb,
*/
static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_)
{
- struct sk_buff *list = ((const struct sk_buff *)list_)->next;
- if (list == (struct sk_buff *)list_)
- list = NULL;
- return list;
+ struct sk_buff *skb = list_->next;
+
+ if (skb == (struct sk_buff *)list_)
+ skb = NULL;
+ return skb;
}
/**
@@ -902,6 +903,7 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
const struct sk_buff_head *list_)
{
struct sk_buff *next = skb->next;
+
if (next == (struct sk_buff *)list_)
next = NULL;
return next;
@@ -922,10 +924,12 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
*/
static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
{
- struct sk_buff *list = ((const struct sk_buff *)list_)->prev;
- if (list == (struct sk_buff *)list_)
- list = NULL;
- return list;
+ struct sk_buff *skb = list_->prev;
+
+ if (skb == (struct sk_buff *)list_)
+ skb = NULL;
+ return skb;
+
}
/**
^ permalink raw reply related
* Re: [PATCH] cxgb3: Don't call cxgb_vlan_mode until q locks are initialized
From: David Miller @ 2012-05-01 2:09 UTC (permalink / raw)
To: roland; +Cc: divy, netdev, roland
In-Reply-To: <1335806147-17310-1-git-send-email-roland@kernel.org>
From: Roland Dreier <roland@kernel.org>
Date: Mon, 30 Apr 2012 10:15:47 -0700
> From: Roland Dreier <roland@purestorage.com>
>
> The driver calls cxgb_vlan_mode() from init_one(). This calls into
> synchronize_rx(), which locks all the q locks, but the q locks are not
> initialized until cxgb_up() -> setup_sge_qsets(). So move the call to
> cxgb_vlan_mode() into cxgb_up(), after the call to setup_sge_qsets().
> We also move the body of these functions up higher to avoid having to
> a forward declaration.
>
> This was found because of the lockdep warning:
...
> Contrary to what lockdep says, the code is not fine: we are locking an
> uninitialized spinlock.
>
> Signed-off-by: Roland Dreier <roland@purestorage.com>
Applied, thanks.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox