From e10eea625f8c07e5c9ec205cf2c6854d9c536b67 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 30 Jul 2011 13:32:56 +0200 Subject: rt2x00: rt2800: fix zeroing skb structure commit b52398b6e4522176dd125722c72c301015d24520 upstream. We should clear skb->data not skb itself. Bug was introduced by: commit 0b8004aa12d13ec750d102ba4082a95f0107c649 "rt2x00: Properly reserve room for descriptors in skbs". Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2a6aa85cc6c..5a4522860a4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -784,8 +784,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) /* * Add space for the TXWI in front of the skb. */ - skb_push(entry->skb, TXWI_DESC_SIZE); - memset(entry->skb, 0, TXWI_DESC_SIZE); + memset(skb_push(entry->skb, TXWI_DESC_SIZE), 0, TXWI_DESC_SIZE); /* * Register descriptor details in skb frame descriptor. -- cgit v1.2.3 From 07e1a60a732bbd4142d068302d09470d8441d1dc Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 2 Aug 2011 13:29:02 +0200 Subject: rt2x00: fix usage of NULL queue commit 00898a47269ae5e6dda04defad00234b96692d95 upstream. We may call rt2x00queue_pause_queue(queue) with queue == NULL. Bug was introduced by commit 62fe778412b36791b7897cfa139342906fbbf07b "rt2x00: Fix stuck queue in tx failure case" . Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rt2x00/rt2x00mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 93bec140e59..a76fdbe6d7d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -113,7 +113,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * due to possible race conditions in mac80211. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - goto exit_fail; + goto exit_free_skb; /* * Use the ATIM queue if appropriate and present. @@ -127,7 +127,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ERROR(rt2x00dev, "Attempt to send packet over invalid queue %d.\n" "Please file bug report to %s.\n", qid, DRV_PROJECT); - goto exit_fail; + goto exit_free_skb; } /* @@ -159,6 +159,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) exit_fail: rt2x00queue_pause_queue(queue); + exit_free_skb: dev_kfree_skb_any(skb); } EXPORT_SYMBOL_GPL(rt2x00mac_tx); -- cgit v1.2.3 From b7d9c861aec35bba7e809eef5b6a79fe3ff8b695 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 29 Jul 2011 10:53:12 -0500 Subject: rtlwifi: Fix kernel oops on ARM SOC commit b6b67df3f24c45af0012ee3c8af2f62ca083ae18 upstream. This driver uses information from the self member of the pci_bus struct to get information regarding the bridge to which the PCIe device is attached. Unfortunately, this member is not established on all architectures, which leads to a kernel oops. Skipping the entire block that uses the self member to determine the bridge vendor will only affect RTL8192DE devices as that driver sets the ASPM support flag differently when the bridge vendor is Intel. If the self member is available, there is no functional change. This patch fixes Bugzilla No. 40212. Reported-by: Hubert Liao Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/rtlwifi/pci.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 254b64ba4bf..c872a232427 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1709,15 +1709,17 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); - /*find bridge info */ - pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; - for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) { - if (bridge_pdev->vendor == pcibridge_vendors[tmp]) { - pcipriv->ndis_adapter.pcibridge_vendor = tmp; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - ("Pci Bridge Vendor is found index: %d\n", - tmp)); - break; + if (bridge_pdev) { + /*find bridge info if available */ + pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; + for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) { + if (bridge_pdev->vendor == pcibridge_vendors[tmp]) { + pcipriv->ndis_adapter.pcibridge_vendor = tmp; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + ("Pci Bridge Vendor is found index:" + " %d\n", tmp)); + break; + } } } -- cgit v1.2.3 From 965045249af402d12228f659cb12a8aead05bbe2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 27 Jul 2011 15:37:43 +0200 Subject: iwlegacy: set tx power after rxon_assoc commit 17e859a899712d16c3e70b045d61ad9e02c53f8a upstream. If settings of tx power was deferred during scan or changing channel we have to setup them during commit rxon. Fix problem on 3945 (4965 already has this fix). Optimize code to apply tx settings only when tx power was actually changed. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlegacy/iwl-3945.c | 6 +++++- drivers/net/wireless/iwlegacy/iwl-4965.c | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c index d096dc28204..dcc1552c046 100644 --- a/drivers/net/wireless/iwlegacy/iwl-3945.c +++ b/drivers/net/wireless/iwlegacy/iwl-3945.c @@ -1747,7 +1747,11 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - + /* + * We do not commit tx power settings while channel changing, + * do it now if tx power changed. + */ + iwl_legacy_set_tx_power(priv, priv->tx_power_next, false); return 0; } diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index facc94e74b0..0a1babb2331 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -1237,7 +1237,12 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); iwl_legacy_print_rx_config_cmd(priv, ctx); - goto set_tx_power; + /* + * We do not commit tx power settings while channel changing, + * do it now if tx power changed. + */ + iwl_legacy_set_tx_power(priv, priv->tx_power_next, false); + return 0; } /* If we are currently associated and the new config requires @@ -1317,7 +1322,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c iwl4965_init_sensitivity(priv); -set_tx_power: /* If we issue a new RXON command which required a tune then we must * send a new TXPOWER command or we won't be able to Tx any frames */ ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true); -- cgit v1.2.3 From cbd1db4bb30ca684d811f4b5bf5dc099aa582445 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 27 Jul 2011 15:01:02 +0200 Subject: ath9k: initialize tx chainmask before testing channel tx power values commit c1227340ca65c2069222a956a68b6842d460c4f4 upstream. With an uninitialized chainmask, the per-channel power will only contain the power limits for a single chain instead of the combined tx power. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/init.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 45c585a337e..5a9fd21faf8 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -665,8 +665,10 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) static void ath9k_init_txpower_limits(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_channel *curchan = ah->curchan; + ah->txchainmask = common->tx_chainmask; if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) -- cgit v1.2.3 From c82ac94469ab54ca57b05fd85ce709530d44002f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 29 Jul 2011 15:59:08 +0200 Subject: ath9k: skip ->config_pci_powersave() if PCIe port has ASPM disabled commit d4930086bdd0c08a8b3a4d66a9c702297cb74a99 upstream. We receive many bug reports about system hang during suspend/resume when ath9k driver is in use. Adrian Chadd remarked that this problem happens on systems that have ASPM disabled. To do not hit the bug, skip doing ->config_pci_powersave magic if PCIe downstream port device, which ath9k device is connected to, has ASPM disabled. Bug was introduced by: commit 53bc7aa08b48e5cd745f986731cc7dc24eef2a9f Author: Vivek Natarajan Date: Mon Apr 5 14:48:04 2010 +0530 ath9k: Add support for newer AR9285 chipsets. Patch should address: https://bugzilla.kernel.org/show_bug.cgi?id=37462 https://bugzilla.kernel.org/show_bug.cgi?id=37082 https://bugzilla.redhat.com/show_bug.cgi?id=697157 however I did not receive confirmation about that, except from Camilo Mesias, whose system stops hang regularly with this patch (but still hangs from time to time, but this is probably some other bug). Tested-by: Camilo Mesias Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 6 +----- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 6 +----- drivers/net/wireless/ath/ath9k/hw.c | 11 +++++++++-- drivers/net/wireless/ath/ath9k/hw.h | 3 ++- drivers/net/wireless/ath/ath9k/pci.c | 27 +++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f344cc2b3d5..c32f9d1b215 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -309,11 +309,7 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, u8 i; u32 val; - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) + if (ah->is_pciexpress != true || ah->aspm_enabled != true) return; /* Nothing to do on restore for 11N */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 392bf0f8ff1..7e02fb4b4b5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -351,11 +351,7 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) { - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) + if (ah->is_pciexpress != true || ah->aspm_enabled != true) return; /* Nothing to do on restore for 11N */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1be7c8bbef8..03900ca7d99 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -299,6 +299,14 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } +static void ath9k_hw_aspm_init(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (common->bus_ops->aspm_init) + common->bus_ops->aspm_init(common); +} + /* This should work for all families including legacy */ static bool ath9k_hw_chip_test(struct ath_hw *ah) { @@ -359,7 +367,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.additional_swba_backoff = 0; ah->config.ack_6mb = 0x0; ah->config.cwm_ignore_extcca = 0; - ah->config.pcie_powersave_enable = 0; ah->config.pcie_clock_req = 0; ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; @@ -577,7 +584,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_aspm_init(ah); else ath9k_hw_disablepcie(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4b157c53d1a..939cc9d76c2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -215,7 +215,6 @@ struct ath9k_ops_config { int additional_swba_backoff; int ack_6mb; u32 cwm_ignore_extcca; - u8 pcie_powersave_enable; bool pcieSerDesWrite; u8 pcie_clock_req; u32 pcie_waen; @@ -671,6 +670,7 @@ struct ath_hw { bool sw_mgmt_crypto; bool is_pciexpress; + bool aspm_enabled; bool is_monitoring; bool need_an_top2_fixup; u16 tx_trig_level; @@ -870,6 +870,7 @@ struct ath_bus_ops { bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); void (*bt_coex_prep)(struct ath_common *common); void (*extn_synch_en)(struct ath_common *common); + void (*aspm_init)(struct ath_common *common); }; static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 3bad0b2cf9a..be4ea132981 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "ath9k.h" @@ -115,12 +116,38 @@ static void ath_pci_extn_synch_enable(struct ath_common *common) pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl); } +static void ath_pci_aspm_init(struct ath_common *common) +{ + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct ath_hw *ah = sc->sc_ah; + struct pci_dev *pdev = to_pci_dev(sc->dev); + struct pci_dev *parent; + int pos; + u8 aspm; + + if (!pci_is_pcie(pdev)) + return; + + parent = pdev->bus->self; + if (WARN_ON(!parent)) + return; + + pos = pci_pcie_cap(parent); + pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); + if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { + ah->aspm_enabled = true; + /* Initialize PCIe PM and SERDES registers. */ + ath9k_hw_configpcipowersave(ah, 0, 0); + } +} + static const struct ath_bus_ops ath_pci_bus_ops = { .ath_bus_type = ATH_PCI, .read_cachesize = ath_pci_read_cachesize, .eeprom_read = ath_pci_eeprom_read, .bt_coex_prep = ath_pci_bt_coex_prep, .extn_synch_en = ath_pci_extn_synch_enable, + .aspm_init = ath_pci_aspm_init, }; static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -- cgit v1.2.3 From ca0acca0f0382ed27f2c64d5db4e8b82b8ff1169 Mon Sep 17 00:00:00 2001 From: Thomas Reim Date: Fri, 29 Jul 2011 14:28:57 +0000 Subject: drm: Separate EDID Header Check from EDID Block Check commit 051963d4832ed61e5ae74f5330b0a94489e101b9 upstream. Provides function drm_edid_header_is_valid() for EDID header check and replaces EDID header check part of function drm_edid_block_valid() by a call of drm_edid_header_is_valid(). This is a prerequisite to extend DDC probing, e. g. in function radeon_ddc_probe() for Radeon devices, by a central EDID header check. Tested for kernel 2.6.35, 2.6.38 and 3.0 Signed-off-by: Thomas Reim Reviewed-by: Alex Deucher Acked-by: Stephen Michaels Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_edid.c | 24 ++++++++++++++++++------ include/drm/drm_crtc.h | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 09292193daf..1bbb85b9ce4 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -127,6 +127,23 @@ static const u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + /* + * Sanity check the header of the base EDID block. Return 8 if the header + * is perfect, down to 0 if it's totally wrong. + */ +int drm_edid_header_is_valid(const u8 *raw_edid) +{ + int i, score = 0; + + for (i = 0; i < sizeof(edid_header); i++) + if (raw_edid[i] == edid_header[i]) + score++; + + return score; +} +EXPORT_SYMBOL(drm_edid_header_is_valid); + + /* * Sanity check the EDID block (base or extension). Return 0 if the block * doesn't check out, or 1 if it's valid. @@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid) struct edid *edid = (struct edid *)raw_edid; if (raw_edid[0] == 0x00) { - int score = 0; - - for (i = 0; i < sizeof(edid_header); i++) - if (raw_edid[i] == edid_header[i]) - score++; - + int score = drm_edid_header_is_valid(raw_edid); if (score == 8) ; else if (score >= 6) { DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 33d12f87f0e..0ec36871e5d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, extern int drm_add_modes_noedid(struct drm_connector *connector, int hdisplay, int vdisplay); +extern int drm_edid_header_is_valid(const u8 *raw_edid); extern bool drm_edid_is_valid(struct edid *edid); struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, int hsize, int vsize, int fresh); -- cgit v1.2.3 From 3567503899af0be5f8df3c5f048d453f7eb0e172 Mon Sep 17 00:00:00 2001 From: Thomas Reim Date: Fri, 29 Jul 2011 14:28:58 +0000 Subject: drm/radeon: Extended DDC Probing for Connectors with Improperly Wired DDC Lines (here: Asus M2A-VM HDMI) commit e384fab8c6f3ca88600bcb2ebdf0eb2f90864fab upstream. Some integrated ATI Radeon chipset implementations with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability of a DDC even when the add-on card is not plugged in or HDMI is disabled in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid() periodically dump data and kernel errors into system log files and onto terminals. For these connectors DDC probing is extended by a check for a correct EDID header. Only in case a valid EDID header is also found, the (HDMI or DVI) connector will be used by the Radeon driver. This prevents the kernel driver from useless flooding of logs and terminal sessions with EDID dumps and error messages. This patch adds a flag 'requires_extended_probe' to the radeon_connector structure. In function radeon_connector_needs_extended_probe() this flag can be set on a chipset family/vendor/connector type specific basis. In addition, function radeon_ddc_probe() has been adapted to perform extended DDC probing if required by the connector's flag. Requires function drm_edid_header_is_valid() in DRM module provided by [PATCH] drm: Separate EDID Header Check from EDID Block Check. Tested for kernel 2.6.35, 2.6.38 and 3.0 on Asus M2A-VM HDMI board BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=668196 BugLink: http://bugs.launchpad.net/bugs/7228066 Signed-off-by: Thomas Reim Reviewed-by: Alex Deucher Acked-by: Stephen Michaels Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 45 ++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/radeon_display.c | 9 ++++++ drivers/gpu/drm/radeon/radeon_i2c.c | 32 +++++++++++++++------ drivers/gpu/drm/radeon/radeon_mode.h | 6 +++- 4 files changed, 80 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9792d4ffdc8..6a0f1befbc1 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -430,6 +430,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr return 0; } +/* + * Some integrated ATI Radeon chipset implementations (e. g. + * Asus M2A-VM HDMI) may indicate the availability of a DDC, + * even when there's no monitor connected. For these connectors + * following DDC probe extension will be applied: check also for the + * availability of EDID with at least a correct EDID header. Only then, + * DDC is assumed to be available. This prevents drm_get_edid() and + * drm_edid_block_valid() from periodically dumping data and kernel + * errors into the logs and onto the terminal. + */ +static bool radeon_connector_needs_extended_probe(struct radeon_device *dev, + uint32_t supported_device, + int connector_type) +{ + /* Asus M2A-VM HDMI board sends data to i2c bus even, + * if HDMI add-on card is not plugged in or HDMI is disabled in + * BIOS. Valid DDC can only be assumed, if also a valid EDID header + * can be retrieved via i2c bus during DDC probe */ + if ((dev->pdev->device == 0x791e) && + (dev->pdev->subsystem_vendor == 0x1043) && + (dev->pdev->subsystem_device == 0x826d)) { + if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) && + (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) + return true; + } + + /* Default: no EDID header probe required for DDC probing */ + return false; +} + static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, struct drm_connector *connector) { @@ -661,7 +691,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, + radeon_connector->requires_extended_probe); if (dret) { if (radeon_connector->edid) { kfree(radeon_connector->edid); @@ -833,7 +864,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) bool dret = false; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, + radeon_connector->requires_extended_probe); if (dret) { if (radeon_connector->edid) { kfree(radeon_connector->edid); @@ -1251,7 +1283,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (radeon_dp_getdpcd(radeon_connector)) ret = connector_status_connected; } else { - if (radeon_ddc_probe(radeon_connector)) + if (radeon_ddc_probe(radeon_connector, + radeon_connector->requires_extended_probe)) ret = connector_status_connected; } } @@ -1406,6 +1439,9 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->shared_ddc = shared_ddc; radeon_connector->connector_object_id = connector_object_id; radeon_connector->hpd = *hpd; + radeon_connector->requires_extended_probe = + radeon_connector_needs_extended_probe(rdev, supported_device, + connector_type); radeon_connector->router = *router; if (router->ddc_valid || router->cd_valid) { radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); @@ -1752,6 +1788,9 @@ radeon_add_legacy_connector(struct drm_device *dev, radeon_connector->devices = supported_device; radeon_connector->connector_object_id = connector_object_id; radeon_connector->hpd = *hpd; + radeon_connector->requires_extended_probe = + radeon_connector_needs_extended_probe(rdev, supported_device, + connector_type); switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 292f73f0ddb..ed085ce90e9 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector) if (!radeon_connector->ddc_bus) return -1; edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); + /* Log EDID retrieval status here. In particular with regard to + * connectors with requires_extended_probe flag set, that will prevent + * function radeon_dvi_detect() to fetch EDID on this connector, + * as long as there is no valid EDID header found */ if (edid) { + DRM_INFO("Radeon display connector %s: Found valid EDID", + drm_get_connector_name(connector)); kfree(edid); + } else { + DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID", + drm_get_connector_name(connector)); } return ret; } diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 781196db792..6c111c1fa3f 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -32,17 +32,17 @@ * radeon_ddc_probe * */ -bool radeon_ddc_probe(struct radeon_connector *radeon_connector) +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe) { - u8 out_buf[] = { 0x0, 0x0}; - u8 buf[2]; + u8 out = 0x0; + u8 buf[8]; int ret; struct i2c_msg msgs[] = { { .addr = 0x50, .flags = 0, .len = 1, - .buf = out_buf, + .buf = &out, }, { .addr = 0x50, @@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) } }; + /* Read 8 bytes from i2c for extended probe of EDID header */ + if (requires_extended_probe) + msgs[1].len = 8; + /* on hw with routers, select right port */ if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); - if (ret == 2) - return true; - - return false; + if (ret != 2) + /* Couldn't find an accessible DDC on this connector */ + return false; + if (requires_extended_probe) { + /* Probe also for valid EDID header + * EDID header starts with: + * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00. + * Only the first 6 bytes must be valid as + * drm_edid_block_valid() can fix the last 2 bytes */ + if (drm_edid_header_is_valid(buf) < 6) { + /* Couldn't find an accessible EDID on this + * connector */ + return false; + } + } + return true; } /* bit banging i2c */ diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6df4e3cec0c..d09031c03e2 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -438,6 +438,9 @@ struct radeon_connector { struct radeon_i2c_chan *ddc_bus; /* some systems have an hdmi and vga port with a shared ddc line */ bool shared_ddc; + /* for some Radeon chip families we apply an additional EDID header + check as part of the DDC probe */ + bool requires_extended_probe; bool use_digital; /* we need to mind the EDID between detect and get modes due to analog/digital/tvencoder */ @@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, u8 val); extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); -extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, + bool requires_extended_probe); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); -- cgit v1.2.3 From 3e7ecfafba28507306979576bb71dd30cc13e2d3 Mon Sep 17 00:00:00 2001 From: Thomas Reim Date: Fri, 29 Jul 2011 14:29:00 +0000 Subject: drm/radeon: Extended DDC Probing for ECS A740GM-M DVI-D Connector commit a81b31e9fc98e067b7e7f1244861c97e44268e2d upstream. ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus for a DVI connector that is not implemented/existent on the board. Fix by applying extented DDC probing for this connector. Requires [PATCH] drm/radeon: Extended DDC Probing for Connectors with Improperly Wired DDC Lines Tested for kernel 2.6.38 on Asus ECS A740GM-M board BugLink: http://bugs.launchpad.net/bugs/810926 Signed-off-by: Thomas Reim Reviewed-by: Alex Deucher Acked-by: Stephen Michaels Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_connectors.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 6a0f1befbc1..6d6b5f16bc0 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -455,6 +455,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev, (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) return true; } + /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus + * for a DVI connector that is not implemented */ + if ((dev->pdev->device == 0x796e) && + (dev->pdev->subsystem_vendor == 0x1019) && + (dev->pdev->subsystem_device == 0x2615)) { + if ((connector_type == DRM_MODE_CONNECTOR_DVID) && + (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) + return true; + } /* Default: no EDID header probe required for DDC probing */ return false; -- cgit v1.2.3 From ed1c13cc2ce278a002f11fe6ce480d717d1f6784 Mon Sep 17 00:00:00 2001 From: Thomas Reim Date: Fri, 29 Jul 2011 14:28:59 +0000 Subject: drm/radeon: Log Subsystem Vendor and Device Information commit d522d9cc5bdd41214084383fc3e6d882f6916a78 upstream. Log PCI subsystem vendor and subsystem device ID in addition to PCI vendor and device ID during kernel mode initialisation. This helps to better identify radeon devices of third-party vendors, e. g. for bug analysis. Tested for kernel 2.6.35, 2.6.38 and 3.0 on Asus M2A-VM HDMI board Signed-off-by: Thomas Reim Reviewed-by: Alex Deucher Acked-by: Stephen Michaels Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/radeon/radeon_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7cfaa7e2f3b..440e6ecccc4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev, rdev->gpu_lockup = false; rdev->accel_working = false; - DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n", - radeon_family_name[rdev->family], pdev->vendor, pdev->device); + DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", + radeon_family_name[rdev->family], pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); /* mutex initialization are all done here so we * can recall function without having locking issues */ -- cgit v1.2.3 From 715245b55733d3a3ca1f336dd0682f83836c7625 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 13 Jul 2011 16:32:32 -0400 Subject: drm/i915/pch: Fix integer math bugs in panel fitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 302983e9059e9ef5de3ca7671918eeb237c5971e upstream. Consider a 1600x900 panel, upscaling a 1360x768 mode, full-aspect. The old math would give you: scaled_width = 1600 * 768; /* 1228800 */ scaled_height = 1360 * 900; /* 1224000 */ if (scaled_width > scaled_height) { /* pillarbox, and true */ width = 1224000 / 768; /* int(1593.75) = 1593 */ x = (1600 - 1593 + 1) / 2; /* 4 */ y = 0; height = 768; } /* ... */ This is broken. The total width of scanout would then be 1593 + 4 + 4, or 1601, which is wider than the panel itself. The hardware very dutifully implements this, and you end up with a black 45° diagonal from the top-left corner to the bottom edge of the screen. It's a cool effect and all, but not what you wanted. Similar things happen for the letterbox case. The problem is that you have an integer number of pixels, which means it's usually impossible to upscale equally on both axes. 1360/768 is 1.7708, 1600/900 is 1.7777. Since we're constrained on the one axis, the other one wants to come out as an even number of pixels (the panel is almost certainly even on both axes, and the x/y offsets will be applied on both sides). In the math above, if 'width' comes out even, rounding down is correct; if it's odd, you'd rather round up. So just increment width/height in those cases. Tested on a Lenovo T500 (Ironlake). Signed-off-by: Adam Jackson Tested-By: Daniel Manrique Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38851 Reviewed-by: Chris Wilson Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_panel.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a06ff07a4d3..05f500cd9c2 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -83,11 +83,15 @@ intel_pch_panel_fitting(struct drm_device *dev, u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; if (scaled_width > scaled_height) { /* pillar */ width = scaled_height / mode->vdisplay; + if (width & 1) + width++; x = (adjusted_mode->hdisplay - width + 1) / 2; y = 0; height = adjusted_mode->vdisplay; } else if (scaled_width < scaled_height) { /* letter */ height = scaled_width / mode->hdisplay; + if (height & 1) + height++; y = (adjusted_mode->vdisplay - height + 1) / 2; x = 0; width = adjusted_mode->hdisplay; -- cgit v1.2.3 From c7b53ef3876b12a225039b930088eec77234661f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 15 Jun 2011 23:32:33 +0200 Subject: drm/i915: load the LUT before pipe enable on ILK+ commit 9c54c0dd948d715ccfd79e97d852f80eeb53254a upstream. Per the specs and to address https://bugs.freedesktop.org/show_bug.cgi?id=36888. Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0f1c799afea..5609c065aaf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2699,14 +2699,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); } + /* + * On ILK+ LUT must be loaded before the pipe is running but with + * clocks enabled + */ + intel_crtc_load_lut(crtc); + intel_enable_pipe(dev_priv, pipe, is_pch_port); intel_enable_plane(dev_priv, plane, pipe); if (is_pch_port) ironlake_pch_enable(crtc); - intel_crtc_load_lut(crtc); - mutex_lock(&dev->struct_mutex); intel_update_fbc(dev); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 3f6846490d30a4b6e127bc522615db58721a8cdc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jul 2011 10:44:39 -0700 Subject: drm/i915: Initialize RCS ring status page address in intel_render_ring_init_dri commit f3234706a77bd6e1592ae71fb3268e04cb030dba upstream. Physically-addressed hardware status pages are initialized early in the driver load process by i915_init_phys_hws. For UMS environments, the ring structure is not initialized until the X server starts. At that point, the entire ring structure is re-initialized with all new values. Any values set in the ring structure (including ring->status_page.page_addr) will be lost when the ring is re-initialized. This patch moves the initialization of the status_page.page_addr value to intel_render_ring_init_dri. Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_dma.c | 6 ++---- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +++ 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 296fbd66f0e..7eef6e11d9a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -61,7 +61,6 @@ static void i915_write_hws_pga(struct drm_device *dev) static int i915_init_phys_hws(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring = LP_RING(dev_priv); /* Program Hardware Status Page */ dev_priv->status_page_dmah = @@ -71,10 +70,9 @@ static int i915_init_phys_hws(struct drm_device *dev) DRM_ERROR("Can not allocate hardware status page\n"); return -ENOMEM; } - ring->status_page.page_addr = - (void __force __iomem *)dev_priv->status_page_dmah->vaddr; - memset_io(ring->status_page.page_addr, 0, PAGE_SIZE); + memset_io((void __force __iomem *)dev_priv->status_page_dmah->vaddr, + 0, PAGE_SIZE); i915_write_hws_pga(dev); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 95c4b142993..1f61fc7b754 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1319,6 +1319,9 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) ring->get_seqno = pc_render_get_seqno; } + if (!I915_NEED_GFX_HWS(dev)) + ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; + ring->dev = dev; INIT_LIST_HEAD(&ring->active_list); INIT_LIST_HEAD(&ring->request_list); -- cgit v1.2.3 From 8b01249b9fe0697eb66e8d0bf41a714d91d039ce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jul 2011 10:04:56 -0700 Subject: drm/i915: Hold mode_config->mutex during hotplug processing commit a65e34c79c88895766ab1f8a5afa451eed26622b upstream. Hotplug detection is a mode setting operation and must hold the struct_mutex or risk colliding with other mode setting operations. In particular, the display port hotplug function attempts to re-train the link if the monitor is supposed to be running when plugged back in. If that happens while mode setting is underway, the link will get scrambled, leaving it in an inconsistent state. This is a special case -- usually the driver mode setting entry points are covered by the upper level DRM code, but in this case the function is invoked as a work function not under the control of DRM. Signed-off-by: Keith Packard Reviewed-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3b03f85ea62..9da2a2c9995 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -306,6 +306,7 @@ static void i915_hotplug_work_func(struct work_struct *work) struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; + mutex_lock(&mode_config->mutex); DRM_DEBUG_KMS("running encoder hotplug functions\n"); list_for_each_entry(encoder, &mode_config->encoder_list, base.head) @@ -314,6 +315,8 @@ static void i915_hotplug_work_func(struct work_struct *work) /* Just fire off a uevent and let userspace tell us what to do */ drm_helper_hpd_irq_event(dev); + + mutex_unlock(&mode_config->mutex); } static void i915_handle_rps_change(struct drm_device *dev) -- cgit v1.2.3 From c1c741511cbe9fe55257959a83d1fa4361afc5dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jul 2011 15:31:19 -0700 Subject: drm/i915: Fixup for 'Hold mode_config->mutex during hotplug' commit 40ee3381dd1010432acc13e907329029096c5bfc upstream. drm_helper_hpd_irq_event queues another work proc to go and deliver the user-space event, and that function also wants to hold the config mutex, so we shouldn't hold the mutex across the drm_helper_hpd_irq_event call. Signed-off-by: Keith Packard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9da2a2c9995..9b1d669f7d4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -313,10 +313,10 @@ static void i915_hotplug_work_func(struct work_struct *work) if (encoder->hot_plug) encoder->hot_plug(encoder); + mutex_unlock(&mode_config->mutex); + /* Just fire off a uevent and let userspace tell us what to do */ drm_helper_hpd_irq_event(dev); - - mutex_unlock(&mode_config->mutex); } static void i915_handle_rps_change(struct drm_device *dev) -- cgit v1.2.3 From e997d47bff5a467262ef224b4cf8cbba2d3eceea Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Aug 2011 20:50:44 -0700 Subject: net: Compute protocol sequence numbers and fragment IDs using MD5. Computers have become a lot faster since we compromised on the partial MD4 hash which we use currently for performance reasons. MD5 is a much safer choice, and is inline with both RFC1948 and other ISS generators (OpenBSD, Solaris, etc.) Furthermore, only having 24-bits of the sequence number be truly unpredictable is a very serious limitation. So the periodic regeneration and 8-bit counter have been removed. We compute and use a full 32-bit sequence number. For ipv6, DCCP was found to use a 32-bit truncated initial sequence number (it needs 43-bits) and that is fixed here as well. Reported-by: Dan Kaminsky Tested-by: Willy Tarreau Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/char/random.c | 334 +------------------------------ include/linux/random.h | 11 - include/net/secure_seq.h | 20 ++ net/core/Makefile | 2 +- net/core/secure_seq.c | 184 +++++++++++++++++ net/dccp/ipv4.c | 1 + net/dccp/ipv6.c | 9 +- net/ipv4/inet_hashtables.c | 1 + net/ipv4/inetpeer.c | 1 + net/ipv4/netfilter/nf_nat_proto_common.c | 1 + net/ipv4/route.c | 1 + net/ipv4/tcp_ipv4.c | 1 + net/ipv6/inet6_hashtables.c | 1 + net/ipv6/tcp_ipv6.c | 1 + 14 files changed, 223 insertions(+), 345 deletions(-) create mode 100644 include/net/secure_seq.h create mode 100644 net/core/secure_seq.c (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index d4ddeba5668..c35a785005b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1300,330 +1300,14 @@ ctl_table random_table[] = { }; #endif /* CONFIG_SYSCTL */ -/******************************************************************** - * - * Random functions for networking - * - ********************************************************************/ - -/* - * TCP initial sequence number picking. This uses the random number - * generator to pick an initial secret value. This value is hashed - * along with the TCP endpoint information to provide a unique - * starting point for each pair of TCP endpoints. This defeats - * attacks which rely on guessing the initial TCP sequence number. - * This algorithm was suggested by Steve Bellovin. - * - * Using a very strong hash was taking an appreciable amount of the total - * TCP connection establishment time, so this is a weaker hash, - * compensated for by changing the secret periodically. - */ - -/* F, G and H are basic MD4 functions: selection, majority, parity */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* - * The generic round function. The application is so specific that - * we don't bother protecting all the arguments with parens, as is generally - * good macro practice, in favor of extra legibility. - * Rotation is separate from addition to prevent recomputation - */ -#define ROUND(f, a, b, c, d, x, s) \ - (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s))) -#define K1 0 -#define K2 013240474631UL -#define K3 015666365641UL +static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - -static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12]) +static int __init random_int_secret_init(void) { - __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; - - /* Round 1 */ - ROUND(F, a, b, c, d, in[ 0] + K1, 3); - ROUND(F, d, a, b, c, in[ 1] + K1, 7); - ROUND(F, c, d, a, b, in[ 2] + K1, 11); - ROUND(F, b, c, d, a, in[ 3] + K1, 19); - ROUND(F, a, b, c, d, in[ 4] + K1, 3); - ROUND(F, d, a, b, c, in[ 5] + K1, 7); - ROUND(F, c, d, a, b, in[ 6] + K1, 11); - ROUND(F, b, c, d, a, in[ 7] + K1, 19); - ROUND(F, a, b, c, d, in[ 8] + K1, 3); - ROUND(F, d, a, b, c, in[ 9] + K1, 7); - ROUND(F, c, d, a, b, in[10] + K1, 11); - ROUND(F, b, c, d, a, in[11] + K1, 19); - - /* Round 2 */ - ROUND(G, a, b, c, d, in[ 1] + K2, 3); - ROUND(G, d, a, b, c, in[ 3] + K2, 5); - ROUND(G, c, d, a, b, in[ 5] + K2, 9); - ROUND(G, b, c, d, a, in[ 7] + K2, 13); - ROUND(G, a, b, c, d, in[ 9] + K2, 3); - ROUND(G, d, a, b, c, in[11] + K2, 5); - ROUND(G, c, d, a, b, in[ 0] + K2, 9); - ROUND(G, b, c, d, a, in[ 2] + K2, 13); - ROUND(G, a, b, c, d, in[ 4] + K2, 3); - ROUND(G, d, a, b, c, in[ 6] + K2, 5); - ROUND(G, c, d, a, b, in[ 8] + K2, 9); - ROUND(G, b, c, d, a, in[10] + K2, 13); - - /* Round 3 */ - ROUND(H, a, b, c, d, in[ 3] + K3, 3); - ROUND(H, d, a, b, c, in[ 7] + K3, 9); - ROUND(H, c, d, a, b, in[11] + K3, 11); - ROUND(H, b, c, d, a, in[ 2] + K3, 15); - ROUND(H, a, b, c, d, in[ 6] + K3, 3); - ROUND(H, d, a, b, c, in[10] + K3, 9); - ROUND(H, c, d, a, b, in[ 1] + K3, 11); - ROUND(H, b, c, d, a, in[ 5] + K3, 15); - ROUND(H, a, b, c, d, in[ 9] + K3, 3); - ROUND(H, d, a, b, c, in[ 0] + K3, 9); - ROUND(H, c, d, a, b, in[ 4] + K3, 11); - ROUND(H, b, c, d, a, in[ 8] + K3, 15); - - return buf[1] + b; /* "most hashed" word */ - /* Alternative: return sum of all words? */ -} -#endif - -#undef ROUND -#undef F -#undef G -#undef H -#undef K1 -#undef K2 -#undef K3 - -/* This should not be decreased so low that ISNs wrap too fast. */ -#define REKEY_INTERVAL (300 * HZ) -/* - * Bit layout of the tcp sequence numbers (before adding current time): - * bit 24-31: increased after every key exchange - * bit 0-23: hash(source,dest) - * - * The implementation is similar to the algorithm described - * in the Appendix of RFC 1185, except that - * - it uses a 1 MHz clock instead of a 250 kHz clock - * - it performs a rekey every 5 minutes, which is equivalent - * to a (source,dest) tulple dependent forward jump of the - * clock by 0..2^(HASH_BITS+1) - * - * Thus the average ISN wraparound time is 68 minutes instead of - * 4.55 hours. - * - * SMP cleanup and lock avoidance with poor man's RCU. - * Manfred Spraul - * - */ -#define COUNT_BITS 8 -#define COUNT_MASK ((1 << COUNT_BITS) - 1) -#define HASH_BITS 24 -#define HASH_MASK ((1 << HASH_BITS) - 1) - -static struct keydata { - __u32 count; /* already shifted to the final position */ - __u32 secret[12]; -} ____cacheline_aligned ip_keydata[2]; - -static unsigned int ip_cnt; - -static void rekey_seq_generator(struct work_struct *work); - -static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); - -/* - * Lock avoidance: - * The ISN generation runs lockless - it's just a hash over random data. - * State changes happen every 5 minutes when the random key is replaced. - * Synchronization is performed by having two copies of the hash function - * state and rekey_seq_generator always updates the inactive copy. - * The copy is then activated by updating ip_cnt. - * The implementation breaks down if someone blocks the thread - * that processes SYN requests for more than 5 minutes. Should never - * happen, and even if that happens only a not perfectly compliant - * ISN is generated, nothing fatal. - */ -static void rekey_seq_generator(struct work_struct *work) -{ - struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; - - get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); - keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS; - smp_wmb(); - ip_cnt++; - schedule_delayed_work(&rekey_work, - round_jiffies_relative(REKEY_INTERVAL)); -} - -static inline struct keydata *get_keyptr(void) -{ - struct keydata *keyptr = &ip_keydata[ip_cnt & 1]; - - smp_rmb(); - - return keyptr; -} - -static __init int seqgen_init(void) -{ - rekey_seq_generator(NULL); + get_random_bytes(random_int_secret, sizeof(random_int_secret)); return 0; } -late_initcall(seqgen_init); - -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, - __be16 sport, __be16 dport) -{ - __u32 seq; - __u32 hash[12]; - struct keydata *keyptr = get_keyptr(); - - /* The procedure is the same as for IPv4, but addresses are longer. - * Thus we must use twothirdsMD4Transform. - */ - - memcpy(hash, saddr, 16); - hash[4] = ((__force u16)sport << 16) + (__force u16)dport; - memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7); - - seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK; - seq += keyptr->count; - - seq += ktime_to_ns(ktime_get_real()); - - return seq; -} -EXPORT_SYMBOL(secure_tcpv6_sequence_number); -#endif - -/* The code below is shamelessly stolen from secure_tcp_sequence_number(). - * All blames to Andrey V. Savochkin . - */ -__u32 secure_ip_id(__be32 daddr) -{ - struct keydata *keyptr; - __u32 hash[4]; - - keyptr = get_keyptr(); - - /* - * Pick a unique starting offset for each IP destination. - * The dest ip address is placed in the starting vector, - * which is then hashed with random data. - */ - hash[0] = (__force __u32)daddr; - hash[1] = keyptr->secret[9]; - hash[2] = keyptr->secret[10]; - hash[3] = keyptr->secret[11]; - - return half_md4_transform(hash, keyptr->secret); -} - -#ifdef CONFIG_INET - -__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport) -{ - __u32 seq; - __u32 hash[4]; - struct keydata *keyptr = get_keyptr(); - - /* - * Pick a unique starting offset for each TCP connection endpoints - * (saddr, daddr, sport, dport). - * Note that the words are placed into the starting vector, which is - * then mixed with a partial MD4 over random data. - */ - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = ((__force u16)sport << 16) + (__force u16)dport; - hash[3] = keyptr->secret[11]; - - seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK; - seq += keyptr->count; - /* - * As close as possible to RFC 793, which - * suggests using a 250 kHz clock. - * Further reading shows this assumes 2 Mb/s networks. - * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. - * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but - * we also need to limit the resolution so that the u32 seq - * overlaps less than one time per MSL (2 minutes). - * Choosing a clock of 64 ns period is OK. (period of 274 s) - */ - seq += ktime_to_ns(ktime_get_real()) >> 6; - - return seq; -} - -/* Generate secure starting point for ephemeral IPV4 transport port search */ -u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) -{ - struct keydata *keyptr = get_keyptr(); - u32 hash[4]; - - /* - * Pick a unique starting offset for each ephemeral port search - * (saddr, daddr, dport) and 48bits of random data. - */ - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = (__force u32)dport ^ keyptr->secret[10]; - hash[3] = keyptr->secret[11]; - - return half_md4_transform(hash, keyptr->secret); -} -EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); - -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, - __be16 dport) -{ - struct keydata *keyptr = get_keyptr(); - u32 hash[12]; - - memcpy(hash, saddr, 16); - hash[4] = (__force u32)dport; - memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7); - - return twothirdsMD4Transform((const __u32 *)daddr, hash); -} -#endif - -#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) -/* Similar to secure_tcp_sequence_number but generate a 48 bit value - * bit's 32-47 increase every key exchange - * 0-31 hash(source, dest) - */ -u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport) -{ - u64 seq; - __u32 hash[4]; - struct keydata *keyptr = get_keyptr(); - - hash[0] = (__force u32)saddr; - hash[1] = (__force u32)daddr; - hash[2] = ((__force u16)sport << 16) + (__force u16)dport; - hash[3] = keyptr->secret[11]; - - seq = half_md4_transform(hash, keyptr->secret); - seq |= ((u64)keyptr->count) << (32 - HASH_BITS); - - seq += ktime_to_ns(ktime_get_real()); - seq &= (1ull << 48) - 1; - - return seq; -} -EXPORT_SYMBOL(secure_dccp_sequence_number); -#endif - -#endif /* CONFIG_INET */ - +late_initcall(random_int_secret_init); /* * Get a random word for internal kernel use only. Similar to urandom but @@ -1631,17 +1315,15 @@ EXPORT_SYMBOL(secure_dccp_sequence_number); * value is not cryptographically secure but for several uses the cost of * depleting entropy is too high */ -DEFINE_PER_CPU(__u32 [4], get_random_int_hash); +DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); unsigned int get_random_int(void) { - struct keydata *keyptr; __u32 *hash = get_cpu_var(get_random_int_hash); - int ret; + unsigned int ret; - keyptr = get_keyptr(); hash[0] += current->pid + jiffies + get_cycles(); - - ret = half_md4_transform(hash, keyptr->secret); + md5_transform(hash, random_int_secret); + ret = hash[0]; put_cpu_var(get_random_int_hash); return ret; diff --git a/include/linux/random.h b/include/linux/random.h index fb7ab9de5f3..d13059f3ea3 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -57,17 +57,6 @@ extern void add_interrupt_randomness(int irq); extern void get_random_bytes(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); -extern __u32 secure_ip_id(__be32 daddr); -extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); -extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, - __be16 dport); -extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport); -extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, - __be16 sport, __be16 dport); -extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, - __be16 sport, __be16 dport); - #ifndef MODULE extern const struct file_operations random_fops, urandom_fops; #endif diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h new file mode 100644 index 00000000000..d97f6892c01 --- /dev/null +++ b/include/net/secure_seq.h @@ -0,0 +1,20 @@ +#ifndef _NET_SECURE_SEQ +#define _NET_SECURE_SEQ + +#include + +extern __u32 secure_ip_id(__be32 daddr); +extern __u32 secure_ipv6_id(const __be32 daddr[4]); +extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); +extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport); +extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); +extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport); +extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); +extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport); + +#endif /* _NET_SECURE_SEQ */ diff --git a/net/core/Makefile b/net/core/Makefile index 8a04dd22cf7..0d357b1c4e5 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -3,7 +3,7 @@ # obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ - gen_stats.o gen_estimator.o net_namespace.o + gen_stats.o gen_estimator.o net_namespace.o secure_seq.o obj-$(CONFIG_SYSCTL) += sysctl_net_core.o diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c new file mode 100644 index 00000000000..45329d7c9dd --- /dev/null +++ b/net/core/secure_seq.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; + +static int __init net_secret_init(void) +{ + get_random_bytes(net_secret, sizeof(net_secret)); + return 0; +} +late_initcall(net_secret_init); + +static u32 seq_scale(u32 seq) +{ + /* + * As close as possible to RFC 793, which + * suggests using a 250 kHz clock. + * Further reading shows this assumes 2 Mb/s networks. + * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. + * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but + * we also need to limit the resolution so that the u32 seq + * overlaps less than one time per MSL (2 minutes). + * Choosing a clock of 64 ns period is OK. (period of 274 s) + */ + return seq + (ktime_to_ns(ktime_get_real()) >> 6); +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport) +{ + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u32 i; + + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) + secret[i] = net_secret[i] + daddr[i]; + secret[4] = net_secret[4] + + (((__force u16)sport << 16) + (__force u16)dport); + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) + secret[i] = net_secret[i]; + + md5_transform(hash, secret); + + return seq_scale(hash[0]); +} +EXPORT_SYMBOL(secure_tcpv6_sequence_number); + +u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport) +{ + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u32 i; + + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) + secret[i] = net_secret[i] + (__force u32) daddr[i]; + secret[4] = net_secret[4] + (__force u32)dport; + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) + secret[i] = net_secret[i]; + + md5_transform(hash, secret); + + return hash[0]; +} +#endif + +#ifdef CONFIG_INET +__u32 secure_ip_id(__be32 daddr) +{ + u32 hash[MD5_DIGEST_WORDS]; + + hash[0] = (__force __u32) daddr; + hash[1] = net_secret[13]; + hash[2] = net_secret[14]; + hash[3] = net_secret[15]; + + md5_transform(hash, net_secret); + + return hash[0]; +} + +__u32 secure_ipv6_id(const __be32 daddr[4]) +{ + __u32 hash[4]; + + memcpy(hash, daddr, 16); + md5_transform(hash, net_secret); + + return hash[0]; +} + +__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) +{ + u32 hash[MD5_DIGEST_WORDS]; + + hash[0] = (__force u32)saddr; + hash[1] = (__force u32)daddr; + hash[2] = ((__force u16)sport << 16) + (__force u16)dport; + hash[3] = net_secret[15]; + + md5_transform(hash, net_secret); + + return seq_scale(hash[0]); +} + +u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) +{ + u32 hash[MD5_DIGEST_WORDS]; + + hash[0] = (__force u32)saddr; + hash[1] = (__force u32)daddr; + hash[2] = (__force u32)dport ^ net_secret[14]; + hash[3] = net_secret[15]; + + md5_transform(hash, net_secret); + + return hash[0]; +} +EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); +#endif + +#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) +u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) +{ + u32 hash[MD5_DIGEST_WORDS]; + u64 seq; + + hash[0] = (__force u32)saddr; + hash[1] = (__force u32)daddr; + hash[2] = ((__force u16)sport << 16) + (__force u16)dport; + hash[3] = net_secret[15]; + + md5_transform(hash, net_secret); + + seq = hash[0] | (((u64)hash[1]) << 32); + seq += ktime_to_ns(ktime_get_real()); + seq &= (1ull << 48) - 1; + + return seq; +} +EXPORT_SYMBOL(secure_dccp_sequence_number); + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport) +{ + u32 secret[MD5_MESSAGE_BYTES / 4]; + u32 hash[MD5_DIGEST_WORDS]; + u64 seq; + u32 i; + + memcpy(hash, saddr, 16); + for (i = 0; i < 4; i++) + secret[i] = net_secret[i] + daddr[i]; + secret[4] = net_secret[4] + + (((__force u16)sport << 16) + (__force u16)dport); + for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++) + secret[i] = net_secret[i]; + + md5_transform(hash, secret); + + seq = hash[0] | (((u64)hash[1]) << 32); + seq += ktime_to_ns(ktime_get_real()); + seq &= (1ull << 48) - 1; + + return seq; +} +EXPORT_SYMBOL(secure_dccpv6_sequence_number); +#endif +#endif diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 8c36adfd191..332639b56f4 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "ackvec.h" #include "ccid.h" diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 8dc4348774a..b74f76117dc 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "dccp.h" #include "ipv6.h" @@ -69,13 +70,7 @@ static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb) dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); } -static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, - __be16 sport, __be16 dport ) -{ - return secure_tcpv6_sequence_number(saddr, daddr, sport, dport); -} - -static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) +static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb) { return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, ipv6_hdr(skb)->saddr.s6_addr32, diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 3c0369a3a66..984ec656b03 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -21,6 +21,7 @@ #include #include +#include #include /* diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index ce616d92cc5..687764544af 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -19,6 +19,7 @@ #include #include #include +#include /* * Theory of operations. diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c index 3e61faf23a9..f52d41ea069 100644 --- a/net/ipv4/netfilter/nf_nat_proto_common.c +++ b/net/ipv4/netfilter/nf_nat_proto_common.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/net/ipv4/route.c b/net/ipv4/route.c index aa13ef10511..36fe0540b1c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -108,6 +108,7 @@ #ifdef CONFIG_SYSCTL #include #endif +#include #define RT_FL_TOS(oldflp4) \ ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 708dc203b03..b3e6956d7ba 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index b5319723370..73f1a00a96a 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -20,6 +20,7 @@ #include #include #include +#include #include int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 87551ca568c..7c43e861475 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -61,6 +61,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From 2c4ee7699067b5f9d65e8d97d153daa5d0590365 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Fri, 1 Jul 2011 11:34:26 +0200 Subject: asus-wmi: fix hwmon/pwm1 commit 49979d091d1847823c064301da1ec173619ddd92 upstream. The code was completly broken, and should never had been sent to the kernel. That's what happens when you write code without hardware to test it. Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-wmi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3c7857c71a2..f6703614468 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -797,8 +797,8 @@ exit: * Hwmon device */ static ssize_t asus_hwmon_pwm1(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct asus_wmi *asus = dev_get_drvdata(dev); u32 value; @@ -809,7 +809,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev, if (err < 0) return err; - value |= 0xFF; + value &= 0xFF; if (value == 1) /* Low Speed */ value = 85; @@ -869,7 +869,7 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, * - reverved bits are non-zero * - sfun and presence bit are not set */ - if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 + if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))) ok = false; } @@ -904,6 +904,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) pr_err("Could not register asus hwmon device\n"); return PTR_ERR(hwmon); } + dev_set_drvdata(hwmon, asus); asus->hwmon_device = hwmon; result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group); if (result) -- cgit v1.2.3 From edf400e549fa34a2004612d9eee543747d73cb48 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Fri, 1 Jul 2011 11:34:38 +0200 Subject: asus-wmi: return proper value in store_cpufv() commit 3df5fdadf6400373a696bb14e27d4771e5f6afb3 upstream. Signed-off-by: Corentin Chary Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-wmi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index f6703614468..e1678b90083 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1165,14 +1165,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER); static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int value; + int value, rv; if (!count || sscanf(buf, "%i", &value) != 1) return -EINVAL; if (value < 0 || value > 2) return -EINVAL; - return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL); + rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL); + if (rv < 0) + return rv; + + return count; } static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv); -- cgit v1.2.3 From b1d3755791db359c3827c59248d9aa5f5f430931 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 28 Jul 2011 02:46:03 +0000 Subject: drivers/net/niu.c: adjust array index [ Upstream commit 956837f7c954443f426a82ba6f17b33488cf9a0c ] Convert array index from the loop bound to the loop index. A simplified version of the semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e1,e2,ar; @@ for(e1 = 0; e1 < e2; e1++) { <... ar[ - e2 + e1 ] ...> } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/niu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index cc25bff0bd3..2f8c351b117 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -9196,7 +9196,7 @@ static int __devinit niu_ldg_init(struct niu *np) first_chan = 0; for (i = 0; i < port; i++) - first_chan += parent->rxchan_per_port[port]; + first_chan += parent->rxchan_per_port[i]; num_chan = parent->rxchan_per_port[port]; for (i = first_chan; i < (first_chan + num_chan); i++) { @@ -9212,7 +9212,7 @@ static int __devinit niu_ldg_init(struct niu *np) first_chan = 0; for (i = 0; i < port; i++) - first_chan += parent->txchan_per_port[port]; + first_chan += parent->txchan_per_port[i]; num_chan = parent->txchan_per_port[port]; for (i = first_chan; i < (first_chan + num_chan); i++) { err = niu_ldg_assign_ldn(np, parent, -- cgit v1.2.3 From 9cf81e790a0d8709cbadbaff73ee40aa944e2ea1 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 26 Jul 2011 06:05:38 +0000 Subject: net: Audit drivers to identify those needing IFF_TX_SKB_SHARING cleared [ Upstream commit 550fd08c2cebad61c548def135f67aba284c6162 ] After the last patch, We are left in a state in which only drivers calling ether_setup have IFF_TX_SKB_SHARING set (we assume that drivers touching real hardware call ether_setup for their net_devices and don't hold any state in their skbs. There are a handful of drivers that violate this assumption of course, and need to be fixed up. This patch identifies those drivers, and marks them as not being able to support the safe transmission of skbs by clearning the IFF_TX_SKB_SHARING flag in priv_flags Signed-off-by: Neil Horman CC: Karsten Keil CC: "David S. Miller" CC: Jay Vosburgh CC: Andy Gospodarek CC: Patrick McHardy CC: Krzysztof Halasa CC: "John W. Linville" CC: Greg Kroah-Hartman CC: Marcel Holtmann CC: Johannes Berg Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_net.c | 3 +++ drivers/net/bonding/bond_main.c | 6 ++++-- drivers/net/ifb.c | 2 +- drivers/net/macvlan.c | 2 +- drivers/net/tun.c | 1 + drivers/net/veth.c | 2 ++ drivers/net/wan/hdlc_fr.c | 5 +++-- drivers/net/wireless/airo.c | 1 + drivers/net/wireless/hostap/hostap_main.c | 1 + drivers/staging/ath6kl/os/linux/ar6000_drv.c | 1 + net/8021q/vlan_dev.c | 2 +- net/bluetooth/bnep/netdev.c | 1 + net/l2tp/l2tp_eth.c | 2 +- net/mac80211/iface.c | 1 + 14 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 97988111e45..b145b5acee9 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2531,6 +2531,9 @@ static void _isdn_setup(struct net_device *dev) /* Setup the generic properties */ dev->flags = IFF_NOARP|IFF_POINTOPOINT; + + /* isdn prepends a header in the tx path, can't share skbs */ + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->header_ops = NULL; dev->netdev_ops = &isdn_netdev_ops; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 63c22b0bb5a..9ea2f21443e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1625,8 +1625,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); - else + else { ether_setup(bond_dev); + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } netdev_bonding_change(bond_dev, NETDEV_POST_TYPE_CHANGE); @@ -4398,7 +4400,7 @@ static void bond_setup(struct net_device *bond_dev) bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; bond_dev->priv_flags |= IFF_BONDING; - bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); /* At first, we block adding VLANs. That's the only way to * prevent problems that occur when adding VLANs over an diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 4fecaed67fc..2b98461cb72 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -145,7 +145,7 @@ static void ifb_setup(struct net_device *dev) dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; - dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); random_ether_addr(dev->dev_addr); } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d6aeaa5f25e..2f3c48da586 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -547,7 +547,7 @@ void macvlan_common_setup(struct net_device *dev) { ether_setup(dev); - dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); dev->netdev_ops = &macvlan_netdev_ops; dev->destructor = free_netdev; dev->header_ops = &macvlan_hard_header_ops, diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5235f48be1b..fb50e5a542f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -528,6 +528,7 @@ static void tun_net_init(struct net_device *dev) dev->netdev_ops = &tap_netdev_ops; /* Ethernet TAP Device */ ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; random_ether_addr(dev->dev_addr); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 8461576fa01..4bf7c6d4ab9 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -262,6 +262,8 @@ static void veth_setup(struct net_device *dev) { ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->netdev_ops = &veth_netdev_ops; dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index fc433f28c04..13f9997ede4 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1083,9 +1083,10 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) used = pvc_is_used(pvc); - if (type == ARPHRD_ETHER) + if (type == ARPHRD_ETHER) { dev = alloc_netdev(0, "pvceth%d", ether_setup); - else + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } else dev = alloc_netdev(0, "pvc%d", pvc_setup); if (!dev) { diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 55cf71fbffe..e1b3e3c134f 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2823,6 +2823,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, dev->wireless_data = &ai->wireless_data; dev->irq = irq; dev->base_addr = port; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; SET_NETDEV_DEV(dev, dmdev); diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index d5084829c9e..89a116fba1d 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -855,6 +855,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local, iface = netdev_priv(dev); ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; /* kernel callbacks */ if (iface) { diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c index aa97efc0e4e..62487a76900 100644 --- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c +++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c @@ -6198,6 +6198,7 @@ int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname) ether_setup(dev); init_netdev(dev, ap_ifname); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; if (register_netdev(dev)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n")); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6e82148edfc..5b4f51d440f 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -694,7 +694,7 @@ void vlan_setup(struct net_device *dev) ether_setup(dev); dev->priv_flags |= IFF_802_1Q_VLAN; - dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); dev->tx_queue_len = 0; dev->netdev_ops = &vlan_netdev_ops; diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 8c100c9dae2..d4f5dff7c95 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -231,6 +231,7 @@ void bnep_net_setup(struct net_device *dev) dev->addr_len = ETH_ALEN; ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->netdev_ops = &bnep_netdev_ops; dev->watchdog_timeo = HZ * 2; diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index a8193f52c13..d2726a74597 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -103,7 +103,7 @@ static struct net_device_ops l2tp_eth_netdev_ops = { static void l2tp_eth_dev_setup(struct net_device *dev) { ether_setup(dev); - + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->netdev_ops = &l2tp_eth_netdev_ops; dev->destructor = free_netdev; } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dee30aea9ab..895eec19f2e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -699,6 +699,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { static void ieee80211_if_setup(struct net_device *dev) { ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->netdev_ops = &ieee80211_dataif_ops; dev->destructor = free_netdev; } -- cgit v1.2.3 From 247460c92c3a5d58496c6d65c4b4604ca0e2ff0e Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Tue, 26 Jul 2011 11:12:27 +0000 Subject: bonding: fix string comparison errors [ Upstream commit f4bb2e9c4fa9e5fdddf90589703613fd1a9c519f ] When a bond contains a device where one name is the subset of another (eth1 and eth10, for example), one cannot properly set the primary device or the currently active device. This was reported and based on work by Takuma Umeya. I also verified the problem and tested that this fix resolves it. V2: A few did not like the the current code or my changes, so I refactored bonding_store_primary and bonding_store_active_slave to be a bit cleaner, dropped the use of strnicmp since we did not really need the comparison to be case insensitive, and formatted the input string from sysfs so a comparison to IFNAMSIZ could be used. I also discovered an error in bonding_store_active_slave that would modify bond->primary_slave rather than bond->curr_active_slave before forcing the bonding driver to choose a new active slave. V3: Actually sending the proper patch.... Signed-off-by: Andy Gospodarek Reported-by: Takuma Umeya Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/bonding/bond_sysfs.c | 133 +++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 88fcb25e554..06246109538 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -992,6 +992,7 @@ static ssize_t bonding_store_primary(struct device *d, int i; struct slave *slave; struct bonding *bond = to_bond(d); + char ifname[IFNAMSIZ]; if (!rtnl_trylock()) return restart_syscall(); @@ -1002,32 +1003,33 @@ static ssize_t bonding_store_primary(struct device *d, if (!USES_PRIMARY(bond->params.mode)) { pr_info("%s: Unable to set primary slave; %s is in mode %d\n", bond->dev->name, bond->dev->name, bond->params.mode); - } else { - bond_for_each_slave(bond, slave, i) { - if (strnicmp - (slave->dev->name, buf, - strlen(slave->dev->name)) == 0) { - pr_info("%s: Setting %s as primary slave.\n", - bond->dev->name, slave->dev->name); - bond->primary_slave = slave; - strcpy(bond->params.primary, slave->dev->name); - bond_select_active_slave(bond); - goto out; - } - } + goto out; + } - /* if we got here, then we didn't match the name of any slave */ + sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ - if (strlen(buf) == 0 || buf[0] == '\n') { - pr_info("%s: Setting primary slave to None.\n", - bond->dev->name); - bond->primary_slave = NULL; - bond_select_active_slave(bond); - } else { - pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n", - bond->dev->name, (int)strlen(buf) - 1, buf); + /* check to see if we are clearing primary */ + if (!strlen(ifname) || buf[0] == '\n') { + pr_info("%s: Setting primary slave to None.\n", + bond->dev->name); + bond->primary_slave = NULL; + bond_select_active_slave(bond); + goto out; + } + + bond_for_each_slave(bond, slave, i) { + if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { + pr_info("%s: Setting %s as primary slave.\n", + bond->dev->name, slave->dev->name); + bond->primary_slave = slave; + strcpy(bond->params.primary, slave->dev->name); + bond_select_active_slave(bond); + goto out; } } + + pr_info("%s: Unable to set %.*s as primary slave.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); @@ -1162,6 +1164,7 @@ static ssize_t bonding_store_active_slave(struct device *d, struct slave *old_active = NULL; struct slave *new_active = NULL; struct bonding *bond = to_bond(d); + char ifname[IFNAMSIZ]; if (!rtnl_trylock()) return restart_syscall(); @@ -1170,56 +1173,62 @@ static ssize_t bonding_store_active_slave(struct device *d, read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); - if (!USES_PRIMARY(bond->params.mode)) + if (!USES_PRIMARY(bond->params.mode)) { pr_info("%s: Unable to change active slave; %s is in mode %d\n", bond->dev->name, bond->dev->name, bond->params.mode); - else { - bond_for_each_slave(bond, slave, i) { - if (strnicmp - (slave->dev->name, buf, - strlen(slave->dev->name)) == 0) { - old_active = bond->curr_active_slave; - new_active = slave; - if (new_active == old_active) { - /* do nothing */ - pr_info("%s: %s is already the current active slave.\n", + goto out; + } + + sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ + + /* check to see if we are clearing active */ + if (!strlen(ifname) || buf[0] == '\n') { + pr_info("%s: Clearing current active slave.\n", + bond->dev->name); + bond->curr_active_slave = NULL; + bond_select_active_slave(bond); + goto out; + } + + bond_for_each_slave(bond, slave, i) { + if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { + old_active = bond->curr_active_slave; + new_active = slave; + if (new_active == old_active) { + /* do nothing */ + pr_info("%s: %s is already the current" + " active slave.\n", + bond->dev->name, + slave->dev->name); + goto out; + } + else { + if ((new_active) && + (old_active) && + (new_active->link == BOND_LINK_UP) && + IS_UP(new_active->dev)) { + pr_info("%s: Setting %s as active" + " slave.\n", bond->dev->name, slave->dev->name); - goto out; + bond_change_active_slave(bond, + new_active); } else { - if ((new_active) && - (old_active) && - (new_active->link == BOND_LINK_UP) && - IS_UP(new_active->dev)) { - pr_info("%s: Setting %s as active slave.\n", - bond->dev->name, - slave->dev->name); - bond_change_active_slave(bond, new_active); - } - else { - pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n", - bond->dev->name, - slave->dev->name, - slave->dev->name); - } - goto out; + pr_info("%s: Could not set %s as" + " active slave; either %s is" + " down or the link is down.\n", + bond->dev->name, + slave->dev->name, + slave->dev->name); } + goto out; } } - - /* if we got here, then we didn't match the name of any slave */ - - if (strlen(buf) == 0 || buf[0] == '\n') { - pr_info("%s: Setting active slave to None.\n", - bond->dev->name); - bond->primary_slave = NULL; - bond_select_active_slave(bond); - } else { - pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n", - bond->dev->name, (int)strlen(buf) - 1, buf); - } } + + pr_info("%s: Unable to set %.*s as active slave.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); -- cgit v1.2.3 From d98630f19f4880bfdb170231ef9f0ba781ecc850 Mon Sep 17 00:00:00 2001 From: Chris Clayton Date: Tue, 26 Jul 2011 12:20:22 +0000 Subject: Fix cdc-phonet build [ Upstream commit a0295a3b6775ab88f5883684e14bbda8d287822d ] Try to send to correct address this time! ---------- Forwarded Message ---------- Subject: [PATCH] Fix cdc-phonet build Date: Saturday 23 Jul 2011 From: Chris Clayton To: linux-net@vger.kernel.org cdc-phonet does not presently build on linux-3.0 because there is no entry for it in drivers/net/Makefile. This patch adds that entry. Signed-off-by: Chris Clayton Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 776a478e629..d5ce0115e06 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -283,6 +283,7 @@ obj-$(CONFIG_USB_HSO) += usb/ obj-$(CONFIG_USB_USBNET) += usb/ obj-$(CONFIG_USB_ZD1201) += usb/ obj-$(CONFIG_USB_IPHETH) += usb/ +obj-$(CONFIG_USB_CDC_PHONET) += usb/ obj-$(CONFIG_WLAN) += wireless/ obj-$(CONFIG_NET_TULIP) += tulip/ -- cgit v1.2.3 From 04124c684acdab48c4d990235d5f16343e55d088 Mon Sep 17 00:00:00 2001 From: Klement Fish Date: Thu, 28 Jul 2011 06:03:22 +0000 Subject: sis190: Rx filter init is needed for MAC address change. [ Upstream commit fe66101f14813b77d84f6450d51772a2af2b81a1 ] Addresses https://bugzilla.kernel.org/show_bug.cgi?id=34552 Signed-off-by: Klement Fish Acked-by: Francois Romieu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/sis190.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b436e007eea..f6d26ab30e8 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1824,6 +1824,16 @@ static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL); } +static int sis190_mac_addr(struct net_device *dev, void *p) +{ + int rc; + + rc = eth_mac_addr(dev, p); + if (!rc) + sis190_init_rxfilter(dev); + return rc; +} + static const struct net_device_ops sis190_netdev_ops = { .ndo_open = sis190_open, .ndo_stop = sis190_close, @@ -1832,7 +1842,7 @@ static const struct net_device_ops sis190_netdev_ops = { .ndo_tx_timeout = sis190_tx_timeout, .ndo_set_multicast_list = sis190_set_rx_mode, .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = sis190_mac_addr, .ndo_validate_addr = eth_validate_addr, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = sis190_netpoll, -- cgit v1.2.3 From 7106159f8bd33bd5e5b0ea2c87e499117fc22c69 Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Thu, 28 Jul 2011 13:18:11 +0000 Subject: r8169: Add support for D-Link 530T rev C1 (Kernel Bug 38862) [ Upstream commit 93a3aa25933461d76141179fc94aa32d5f9d954a ] The D-Link DGE-530T rev C1 is a re-badged Realtek 8169 named DLG10028C, unlike the previous revisions which were skge based. It is probably the same as the discontinued DGE-528T (0x4300) other than the PCI ID. The PCI ID is 0x1186:0x4302. Adding it to r8169.c where 0x1186:0x4300 is already found makes the card be detected and work. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=38862 Signed-off-by: Len Sorensen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/r8169.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 5990621fb5c..5f838ef9249 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -236,6 +236,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, { PCI_VENDOR_ID_LINKSYS, 0x1032, -- cgit v1.2.3 From 3e244baaa667ffb2bf7aa8f7d165d40e4899517d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 8 Aug 2011 20:53:58 -0600 Subject: iwlagn: 5000 do not support idle mode commit f35291082294ca6737953bbe4e9491ede04ab822 upstream. 5000 series has issue supporting power save idle mode: commit 9dc2153315650eae220898668b6aa56a25c130be iwlwifi: always support idle mode for agn devices For agn devices, always support idle mode which help power consumption in idle unassociated state. the above changes cause 5000 become not stable when power management is "on" http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2312 Reported-by: Devin J. Pohly Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville Signed-off-by: Devin J. Pohly Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-power.c | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e816c27db79..f1c3f49c0fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -421,6 +421,7 @@ static struct iwl_base_params iwl5000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, + .no_idle_support = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a54d416ec34..b76996ae15f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -195,6 +195,7 @@ struct iwl_mod_params { * @temperature_kelvin: temperature report by uCode in kelvin * @max_event_log_size: size of event log buffer size for ucode event logging * @shadow_reg_enable: HW shadhow register bit + * @no_idle_support: do not support idle mode */ struct iwl_base_params { int eeprom_size; @@ -216,6 +217,7 @@ struct iwl_base_params { bool temperature_kelvin; u32 max_event_log_size; const bool shadow_reg_enable; + const bool no_idle_support; }; /* * @advanced_bt_coexist: support advanced bt coexist diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 595c930b28a..4a05a6ace3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -355,7 +355,8 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) + if (!priv->cfg->base_params->no_idle_support && + priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (iwl_tt_is_low_power_state(priv)) { /* in thermal throttling low power state */ -- cgit v1.2.3 From fb07bb91081d60b29b3eb1372fc0e61ded2be352 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Tue, 14 Jun 2011 10:54:56 +0530 Subject: mpt2sas: Fixed Big Indian Issues on 32 bit PPC commit c97951ec46d4b076c2236b77db34eeed6dddb8eb upstream. This patch addresses many endian issues solved by runing sparse with the option __CHECK_ENDIAN__ turned on. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley Cc: David Miller Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/mpt2sas/mpt2sas_base.c | 65 ++++++++++++-------------------- drivers/scsi/mpt2sas/mpt2sas_base.h | 53 ++++++++++++++++++++++++-- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 10 ++--- drivers/scsi/mpt2sas/mpt2sas_debug.h | 2 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 12 +++--- drivers/scsi/mpt2sas/mpt2sas_transport.c | 24 +++++------- 6 files changed, 96 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index efa0255491c..1da606cb246 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -94,7 +94,7 @@ module_param(diag_buffer_enable, int, 0); MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); -int mpt2sas_fwfault_debug; +static int mpt2sas_fwfault_debug; MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " "and halt firmware - (default=0)"); @@ -857,7 +857,7 @@ _base_interrupt(int irq, void *bus_id) completed_cmds = 0; cb_idx = 0xFF; do { - rd.word = rpf->Words; + rd.word = le64_to_cpu(rpf->Words); if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) goto out; reply = 0; @@ -906,7 +906,7 @@ _base_interrupt(int irq, void *bus_id) next: - rpf->Words = ULLONG_MAX; + rpf->Words = cpu_to_le64(ULLONG_MAX); ioc->reply_post_host_index = (ioc->reply_post_host_index == (ioc->reply_post_queue_depth - 1)) ? 0 : ioc->reply_post_host_index + 1; @@ -1817,7 +1817,9 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) char desc[16]; u8 revision; u32 iounit_pg1_flags; + u32 bios_version; + bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision); strncpy(desc, ioc->manu_pg0.ChipName, 16); printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), " @@ -1828,10 +1830,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, ioc->facts.FWVersion.Word & 0x000000FF, revision, - (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24, - (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16, - (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8, - ioc->bios_pg3.BiosVersion & 0x000000FF); + (bios_version & 0xFF000000) >> 24, + (bios_version & 0x00FF0000) >> 16, + (bios_version & 0x0000FF00) >> 8, + bios_version & 0x000000FF); _base_display_dell_branding(ioc); _base_display_intel_branding(ioc); @@ -2150,7 +2152,7 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) static int _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) { - Mpi2IOCFactsReply_t *facts; + struct mpt2sas_facts *facts; u32 queue_size, queue_diff; u16 max_sge_elements; u16 num_of_reply_frames; @@ -2783,7 +2785,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, int i; u8 failed; u16 dummy; - u32 *mfp; + __le32 *mfp; /* make sure doorbell is not in use */ if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { @@ -2871,7 +2873,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, writel(0, &ioc->chip->HostInterruptStatus); if (ioc->logging_level & MPT_DEBUG_INIT) { - mfp = (u32 *)reply; + mfp = (__le32 *)reply; printk(KERN_INFO "\toffset:data\n"); for (i = 0; i < reply_bytes/4; i++) printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, @@ -3097,7 +3099,8 @@ static int _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag) { Mpi2PortFactsRequest_t mpi_request; - Mpi2PortFactsReply_t mpi_reply, *pfacts; + Mpi2PortFactsReply_t mpi_reply; + struct mpt2sas_port_facts *pfacts; int mpi_reply_sz, mpi_request_sz, r; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, @@ -3139,7 +3142,8 @@ static int _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) { Mpi2IOCFactsRequest_t mpi_request; - Mpi2IOCFactsReply_t mpi_reply, *facts; + Mpi2IOCFactsReply_t mpi_reply; + struct mpt2sas_facts *facts; int mpi_reply_sz, mpi_request_sz, r; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, @@ -3225,17 +3229,6 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); - /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was - * removed and made reserved. For those with older firmware will need - * this fix. It was decided that the Reply and Request frame sizes are - * the same. - */ - if ((ioc->facts.HeaderVersion >> 8) < 0xA) { - mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz); -/* mpi_request.SystemReplyFrameSize = - * cpu_to_le16(ioc->reply_sz); - */ - } mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); mpi_request.ReplyDescriptorPostQueueDepth = @@ -3243,25 +3236,17 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) mpi_request.ReplyFreeQueueDepth = cpu_to_le16(ioc->reply_free_queue_depth); -#if BITS_PER_LONG > 32 mpi_request.SenseBufferAddressHigh = - cpu_to_le32(ioc->sense_dma >> 32); + cpu_to_le32((u64)ioc->sense_dma >> 32); mpi_request.SystemReplyAddressHigh = - cpu_to_le32(ioc->reply_dma >> 32); + cpu_to_le32((u64)ioc->reply_dma >> 32); mpi_request.SystemRequestFrameBaseAddress = - cpu_to_le64(ioc->request_dma); + cpu_to_le64((u64)ioc->request_dma); mpi_request.ReplyFreeQueueAddress = - cpu_to_le64(ioc->reply_free_dma); + cpu_to_le64((u64)ioc->reply_free_dma); mpi_request.ReplyDescriptorPostQueueAddress = - cpu_to_le64(ioc->reply_post_free_dma); -#else - mpi_request.SystemRequestFrameBaseAddress = - cpu_to_le32(ioc->request_dma); - mpi_request.ReplyFreeQueueAddress = - cpu_to_le32(ioc->reply_free_dma); - mpi_request.ReplyDescriptorPostQueueAddress = - cpu_to_le32(ioc->reply_post_free_dma); -#endif + cpu_to_le64((u64)ioc->reply_post_free_dma); + /* This time stamp specifies number of milliseconds * since epoch ~ midnight January 1, 1970. @@ -3271,10 +3256,10 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) (current_time.tv_usec / 1000)); if (ioc->logging_level & MPT_DEBUG_INIT) { - u32 *mfp; + __le32 *mfp; int i; - mfp = (u32 *)&mpi_request; + mfp = (__le32 *)&mpi_request; printk(KERN_INFO "\toffset:data\n"); for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4, @@ -3759,7 +3744,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* initialize Reply Post Free Queue */ for (i = 0; i < ioc->reply_post_queue_depth; i++) - ioc->reply_post_free[i].Words = ULLONG_MAX; + ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX); r = _base_send_ioc_init(ioc, sleep_flag); if (r) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index dcc289c2545..451dc1ce228 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -541,6 +541,53 @@ struct _tr_list { typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); +/* IOC Facts and Port Facts converted from little endian to cpu */ +union mpi2_version_union { + MPI2_VERSION_STRUCT Struct; + u32 Word; +}; + +struct mpt2sas_facts { + u16 MsgVersion; + u16 HeaderVersion; + u8 IOCNumber; + u8 VP_ID; + u8 VF_ID; + u16 IOCExceptions; + u16 IOCStatus; + u32 IOCLogInfo; + u8 MaxChainDepth; + u8 WhoInit; + u8 NumberOfPorts; + u8 MaxMSIxVectors; + u16 RequestCredit; + u16 ProductID; + u32 IOCCapabilities; + union mpi2_version_union FWVersion; + u16 IOCRequestFrameSize; + u16 Reserved3; + u16 MaxInitiators; + u16 MaxTargets; + u16 MaxSasExpanders; + u16 MaxEnclosures; + u16 ProtocolFlags; + u16 HighPriorityCredit; + u16 MaxReplyDescriptorPostQueueDepth; + u8 ReplyFrameSize; + u8 MaxVolumes; + u16 MaxDevHandle; + u16 MaxPersistentEntries; + u16 MinDevHandle; +}; + +struct mpt2sas_port_facts { + u8 PortNumber; + u8 VP_ID; + u8 VF_ID; + u8 PortType; + u16 MaxPostedCmdBuffers; +}; + /** * struct MPT2SAS_ADAPTER - per adapter struct * @list: ioc_list @@ -749,8 +796,8 @@ struct MPT2SAS_ADAPTER { u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; /* static config pages */ - Mpi2IOCFactsReply_t facts; - Mpi2PortFactsReply_t *pfacts; + struct mpt2sas_facts facts; + struct mpt2sas_port_facts *pfacts; Mpi2ManufacturingPage0_t manu_pg0; Mpi2BiosPage2_t bios_pg2; Mpi2BiosPage3_t bios_pg3; @@ -840,7 +887,7 @@ struct MPT2SAS_ADAPTER { /* reply free queue */ u16 reply_free_queue_depth; - u32 *reply_free; + __le32 *reply_free; dma_addr_t reply_free_dma; struct dma_pool *reply_free_dma_pool; u32 reply_free_host_index; diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 437c2d94c45..d1c3bba7e93 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -2706,13 +2706,13 @@ static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL); struct DIAG_BUFFER_START { - u32 Size; - u32 DiagVersion; + __le32 Size; + __le32 DiagVersion; u8 BufferType; u8 Reserved[3]; - u32 Reserved1; - u32 Reserved2; - u32 Reserved3; + __le32 Reserved1; + __le32 Reserved2; + __le32 Reserved3; }; /** * _ctl_host_trace_buffer_size_show - host buffer size (trace only) diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h index 3dcddfeb6f4..9731f8e661b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_debug.h +++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h @@ -164,7 +164,7 @@ static inline void _debug_dump_mf(void *mpi_request, int sz) { int i; - u32 *mfp = (u32 *)mpi_request; + __le32 *mfp = (__le32 *)mpi_request; printk(KERN_INFO "mf:\n\t"); for (i = 0; i < sz; i++) { diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index a7dbc6825f5..e327a3c0360 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1956,7 +1956,7 @@ _scsih_slave_configure(struct scsi_device *sdev) case MPI2_RAID_VOL_TYPE_RAID1E: qdepth = MPT2SAS_RAID_QUEUE_DEPTH; if (ioc->manu_pg10.OEMIdentifier && - (ioc->manu_pg10.GenericFlags0 & + (le32_to_cpu(ioc->manu_pg10.GenericFlags0) & MFG10_GF0_R10_DISPLAY) && !(raid_device->num_pds % 2)) r_level = "RAID10"; @@ -4598,7 +4598,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) Mpi2SasEnclosurePage0_t enclosure_pg0; u32 ioc_status; u16 parent_handle; - __le64 sas_address, sas_address_parent = 0; + u64 sas_address, sas_address_parent = 0; int i; unsigned long flags; struct _sas_port *mpt2sas_port = NULL; @@ -5404,7 +5404,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, { struct MPT2SAS_TARGET *target_priv_data; struct _sas_device *sas_device; - __le64 sas_address; + u64 sas_address; unsigned long flags; Mpi2EventDataSasDeviceStatusChange_t *event_data = fw_event->event_data; @@ -6566,7 +6566,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc) Mpi2ExpanderPage0_t expander_pg0; Mpi2ConfigReply_t mpi_reply; u16 ioc_status; - __le64 sas_address; + u64 sas_address; u16 handle; printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); @@ -7505,7 +7505,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) { struct Scsi_Host *shost = pci_get_drvdata(pdev); struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); - u32 device_state; + pci_power_t device_state; mpt2sas_base_stop_watchdog(ioc); scsi_block_requests(shost); @@ -7532,7 +7532,7 @@ _scsih_resume(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); - u32 device_state = pdev->current_state; + pci_power_t device_state = pdev->current_state; int r; printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous " diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index cb1cdecbe0f..15c79802621 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -299,7 +299,6 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, void *data_out = NULL; dma_addr_t data_out_dma; u32 sz; - u64 *sas_address_le; u16 wait_state_count; if (ioc->shost_recovery || ioc->pci_error_recovery) { @@ -372,8 +371,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, mpi_request->PhysicalPort = 0xFF; mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - sas_address_le = (u64 *)&mpi_request->SASAddress; - *sas_address_le = cpu_to_le64(sas_address); + mpi_request->SASAddress = cpu_to_le64(sas_address); mpi_request->RequestDataLength = cpu_to_le16(sizeof(struct rep_manu_request)); psge = &mpi_request->SGL; @@ -1049,14 +1047,14 @@ struct phy_error_log_reply{ u8 function; /* 0x11 */ u8 function_result; u8 response_length; - u16 expander_change_count; + __be16 expander_change_count; u8 reserved_1[3]; u8 phy_identifier; u8 reserved_2[2]; - u32 invalid_dword; - u32 running_disparity_error; - u32 loss_of_dword_sync; - u32 phy_reset_problem; + __be32 invalid_dword; + __be32 running_disparity_error; + __be32 loss_of_dword_sync; + __be32 phy_reset_problem; }; /** @@ -1085,7 +1083,6 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, void *data_out = NULL; dma_addr_t data_out_dma; u32 sz; - u64 *sas_address_le; u16 wait_state_count; if (ioc->shost_recovery || ioc->pci_error_recovery) { @@ -1160,8 +1157,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, mpi_request->PhysicalPort = 0xFF; mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - sas_address_le = (u64 *)&mpi_request->SASAddress; - *sas_address_le = cpu_to_le64(phy->identify.sas_address); + mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); mpi_request->RequestDataLength = cpu_to_le16(sizeof(struct phy_error_log_request)); psge = &mpi_request->SGL; @@ -1406,7 +1402,6 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc, void *data_out = NULL; dma_addr_t data_out_dma; u32 sz; - u64 *sas_address_le; u16 wait_state_count; if (ioc->shost_recovery) { @@ -1486,8 +1481,7 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc, mpi_request->PhysicalPort = 0xFF; mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - sas_address_le = (u64 *)&mpi_request->SASAddress; - *sas_address_le = cpu_to_le64(phy->identify.sas_address); + mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); mpi_request->RequestDataLength = cpu_to_le16(sizeof(struct phy_error_log_request)); psge = &mpi_request->SGL; @@ -1914,7 +1908,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, mpi_request->PhysicalPort = 0xFF; mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - *((u64 *)&mpi_request->SASAddress) = (rphy) ? + mpi_request->SASAddress = (rphy) ? cpu_to_le64(rphy->identify.sas_address) : cpu_to_le64(ioc->sas_hba.sas_address); mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); -- cgit v1.2.3 From 716ae31687f2d778ff9a18e7286deca992dfa955 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 22 Jul 2011 06:21:51 +0000 Subject: e1000e: alternate MAC address does not work on device id 0x1060 commit c407bee8a56d874b91f3e4ee790660959ff1a25e upstream. This issue is present all the way back to 2.6.34 kernels. Signed-off-by: Bruce Allan Tested-by: Jeffrey Pieper Signed-off-by: Jeff Kirsher Signed-off-by: Greg Kroah-Hartman --- drivers/net/e1000e/lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index dd8ab05b559..8d286023221 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -190,7 +190,8 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ if (!((nvm_data & NVM_COMPAT_LOM) || (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || - (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD))) + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES))) goto out; ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, -- cgit v1.2.3 From 716fa319182000c26521cb2bd4ea034256230f5d Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sat, 6 Aug 2011 21:03:03 +0000 Subject: gianfar: fix fiper alignment after resetting the time commit cbc056602c7c63620c86904c431ff6b61e029dcc upstream. After resetting the time, the PPS signals on the FIPER output channels are incorrectly offset from the clock time, as can be readily verified by a looping back the FIPER to the external time stamp input. Despite its name, setting the "Fiper Realignment Disable" bit seems to fix the problem, at least on the P2020. Also, following the example code from the Freescale BSP, it is not really necessary to disable and re-enable the timer in order to reprogram the FIPER. (The documentation is rather unclear on this point. It seems that writing to the alarm register also disables the FIPER.) Signed-off-by: Richard Cochran Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/gianfar_ptp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c index d8e175382d1..c4134790d68 100644 --- a/drivers/net/gianfar_ptp.c +++ b/drivers/net/gianfar_ptp.c @@ -193,14 +193,9 @@ static void set_alarm(struct etsects *etsects) /* Caller must hold etsects->lock. */ static void set_fipers(struct etsects *etsects) { - u32 tmr_ctrl = gfar_read(&etsects->regs->tmr_ctrl); - - gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl & (~TE)); - gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); + set_alarm(etsects); gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); - set_alarm(etsects); - gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|TE); } /* @@ -511,7 +506,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); set_alarm(etsects); - gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE); + gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE|FRD); spin_unlock_irqrestore(&etsects->lock, flags); -- cgit v1.2.3 From fa54ab17fd26a469755f36f81fd4dad9e33f4f66 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sat, 6 Aug 2011 21:03:04 +0000 Subject: dp83640: increase receive time stamp buffer size commit 8028837d71ba9904b17281b40f94b93e947fbe38 upstream. The dp83640 buffers receive time stamps from special PHY status frames, matching them to received PTP packets in a work queue. Because the timeout for orphaned time stamps is so long and the buffer is so small, the driver can drop time stamps under moderate PTP traffic. This commit fixes the issue by decreasing the timeout to (at least) one timer tick and increasing the buffer size. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/dp83640.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 2cd8dc5847b..cb6e0b486b1 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -34,8 +34,7 @@ #define PAGESEL 0x13 #define LAYER4 0x02 #define LAYER2 0x01 -#define MAX_RXTS 4 -#define MAX_TXTS 4 +#define MAX_RXTS 64 #define N_EXT_TS 1 #define PSF_PTPVER 2 #define PSF_EVNT 0x4000 @@ -218,7 +217,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts) rxts->seqid = p->seqid; rxts->msgtype = (p->msgtype >> 12) & 0xf; rxts->hash = p->msgtype & 0x0fff; - rxts->tmo = jiffies + HZ; + rxts->tmo = jiffies + 2; } static u64 phy2txts(struct phy_txts *p) -- cgit v1.2.3 From 5b61b4c55862e0403795bc4f7a8348accc3ca987 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 29 Jul 2011 17:38:15 +0530 Subject: ath9k_hw: Fix incorrect Tx control power in AR9003 template commit 15052f81d255eac44e745bc630b36aa86779ad9d upstream. CTL power data incorrect in ctlPowerData_2G field of ar9300_eeprom. Setting incorrect CTL power in calibration is causing lower tx power. Tx power was reported as 3dBm while operating in channel 6 HT40+/ in channel 11 HT40- due to CTL powers in the calibration is set to zero. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ff8150e46f0..7e07f0fe031 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -306,7 +306,7 @@ static const struct ar9300_eeprom ar9300_default = { { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, - { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, @@ -883,7 +883,7 @@ static const struct ar9300_eeprom ar9300_x113 = { { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, - { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, @@ -2039,7 +2039,7 @@ static const struct ar9300_eeprom ar9300_x112 = { { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, - { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, + { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, -- cgit v1.2.3 From 05362c29b1639185999b695cdaa37e0c1c15444a Mon Sep 17 00:00:00 2001 From: Alex Hacker Date: Thu, 4 Aug 2011 13:47:32 +0600 Subject: ath9k: fix a misprint which leads to incorrect calibration commit 118c9db51e7acaf8f16deae8311cce6588b83e31 upstream. This patch addresses an issue with incorrect HW register AR_PHY_TX_IQCAL_CORR_COEFF_B1 definition which leads to incorrect clibration. Signed-off-by: Alex Hacker Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 443090d278e..efdbe98fa7e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -848,7 +848,7 @@ #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) -#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM_BASE + 0x450 + ((_i) << 2)) +#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2)) /* * Channel 2 Register Map -- cgit v1.2.3