diff options
51 files changed, 521 insertions, 180 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 471c7f3..15853be 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.7.3" -#define DRV_MODULE_RELDATE "January 29, 2008" +#define DRV_MODULE_VERSION "1.7.4" +#define DRV_MODULE_RELDATE "February 18, 2008" #define RUN_AT(x) (jiffies + (x)) @@ -1273,14 +1273,20 @@ bnx2_set_link(struct bnx2 *bp) if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && (CHIP_NUM(bp) == CHIP_NUM_5706)) { - u32 val; + u32 val, an_dbg; if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { bnx2_5706s_force_link_dn(bp, 0); bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; } val = REG_RD(bp, BNX2_EMAC_STATUS); - if (val & BNX2_EMAC_STATUS_LINK) + + bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); + bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); + bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); + + if ((val & BNX2_EMAC_STATUS_LINK) && + !(an_dbg & MISC_SHDW_AN_DBG_NOSYNC)) bmsr |= BMSR_LSTATUS; else bmsr &= ~BMSR_LSTATUS; @@ -5356,11 +5362,15 @@ bnx2_test_intr(struct bnx2 *bp) return -ENODEV; } +/* Determining link for parallel detection. */ static int bnx2_5706_serdes_has_link(struct bnx2 *bp) { u32 mode_ctl, an_dbg, exp; + if (bp->phy_flags & BNX2_PHY_FLAG_NO_PARALLEL) + return 0; + bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_MODE_CTL); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &mode_ctl); @@ -5390,13 +5400,6 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) int check_link = 1; spin_lock(&bp->phy_lock); - if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { - bnx2_5706s_force_link_dn(bp, 0); - bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; - spin_unlock(&bp->phy_lock); - return; - } - if (bp->serdes_an_pending) { bp->serdes_an_pending--; check_link = 0; @@ -5420,7 +5423,6 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) (bp->phy_flags & BNX2_PHY_FLAG_PARALLEL_DETECT)) { u32 phy2; - check_link = 0; bnx2_write_phy(bp, 0x17, 0x0f01); bnx2_read_phy(bp, 0x15, &phy2); if (phy2 & 0x20) { @@ -5435,17 +5437,21 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) } else bp->current_interval = bp->timer_interval; - if (bp->link_up && (bp->autoneg & AUTONEG_SPEED) && check_link) { + if (check_link) { u32 val; bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &val); - if (val & MISC_SHDW_AN_DBG_NOSYNC) { - bnx2_5706s_force_link_dn(bp, 1); - bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN; - } + if (bp->link_up && (val & MISC_SHDW_AN_DBG_NOSYNC)) { + if (!(bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN)) { + bnx2_5706s_force_link_dn(bp, 1); + bp->phy_flags |= BNX2_PHY_FLAG_FORCED_DOWN; + } else + bnx2_set_link(bp); + } else if (!bp->link_up && !(val & MISC_SHDW_AN_DBG_NOSYNC)) + bnx2_set_link(bp); } spin_unlock(&bp->phy_lock); } @@ -7326,7 +7332,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_NO_WOL; bp->wol = 0; } - if (CHIP_NUM(bp) != CHIP_NUM_5706) { + if (CHIP_NUM(bp) == CHIP_NUM_5706) { + /* Don't do parallel detect on this board because of + * some board problems. The link will not go down + * if we do parallel detect. + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP && + pdev->subsystem_device == 0x310c) + bp->phy_flags |= BNX2_PHY_FLAG_NO_PARALLEL; + } else { bp->phy_addr = 2; if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 3aa0364..1eaf5bb 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6673,6 +6673,7 @@ struct bnx2 { #define BNX2_PHY_FLAG_DIS_EARLY_DAC 0x00000400 #define BNX2_PHY_FLAG_REMOTE_PHY_CAP 0x00000800 #define BNX2_PHY_FLAG_FORCED_DOWN 0x00001000 +#define BNX2_PHY_FLAG_NO_PARALLEL 0x00002000 u32 mii_bmcr; u32 mii_bmsr; diff --git a/drivers/net/niu.c b/drivers/net/niu.c index e98ce1e..d11ba61 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -1616,12 +1616,13 @@ static int niu_enable_alt_mac(struct niu *np, int index, int on) if (index >= niu_num_alt_addr(np)) return -EINVAL; - if (np->flags & NIU_FLAGS_XMAC) + if (np->flags & NIU_FLAGS_XMAC) { reg = XMAC_ADDR_CMPEN; - else + mask = 1 << index; + } else { reg = BMAC_ADDR_CMPEN; - - mask = 1 << index; + mask = 1 << (index + 1); + } val = nr64_mac(reg); if (on) diff --git a/drivers/net/niu.h b/drivers/net/niu.h index 0e8626a..59dc05fc 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -499,7 +499,7 @@ #define BMAC_ADDR2 0x00110UL #define BMAC_ADDR2_ADDR2 0x000000000000ffffULL -#define BMAC_NUM_ALT_ADDR 7 +#define BMAC_NUM_ALT_ADDR 6 #define BMAC_ALT_ADDR0(NUM) (0x00118UL + (NUM)*0x18UL) #define BMAC_ALT_ADDR0_ADDR0 0x000000000000ffffULL diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index db606b6..26ffb67 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8781,7 +8781,7 @@ static int tg3_phys_id(struct net_device *dev, u32 data) return -EAGAIN; if (data == 0) - data = 2; + data = UINT_MAX / 2; for (i = 0; i < (data * 2); i++) { if ((i % 2) == 0) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 3f67a29..e2ad98b 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -244,18 +244,6 @@ static int veth_open(struct net_device *dev) return 0; } -static int veth_close(struct net_device *dev) -{ - struct veth_priv *priv; - - if (netif_carrier_ok(dev)) { - priv = netdev_priv(dev); - netif_carrier_off(dev); - netif_carrier_off(priv->peer); - } - return 0; -} - static int veth_dev_init(struct net_device *dev) { struct veth_net_stats *stats; @@ -286,13 +274,50 @@ static void veth_setup(struct net_device *dev) dev->hard_start_xmit = veth_xmit; dev->get_stats = veth_get_stats; dev->open = veth_open; - dev->stop = veth_close; dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; dev->init = veth_dev_init; dev->destructor = veth_dev_free; } +static void veth_change_state(struct net_device *dev) +{ + struct net_device *peer; + struct veth_priv *priv; + + priv = netdev_priv(dev); + peer = priv->peer; + + if (netif_carrier_ok(peer)) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else { + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); + } +} + +static int veth_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + if (dev->open != veth_open) + goto out; + + switch (event) { + case NETDEV_CHANGE: + veth_change_state(dev); + break; + } +out: + return NOTIFY_DONE; +} + +static struct notifier_block veth_notifier_block __read_mostly = { + .notifier_call = veth_device_event, +}; + /* * netlink interface */ @@ -454,12 +479,14 @@ static struct rtnl_link_ops veth_link_ops = { static __init int veth_init(void) { + register_netdevice_notifier(&veth_notifier_block); return rtnl_link_register(&veth_link_ops); } static __exit void veth_exit(void) { rtnl_link_unregister(&veth_link_ops); + unregister_netdevice_notifier(&veth_notifier_block); } module_init(veth_init); diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index c79066b..69dea33 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -1035,7 +1035,7 @@ struct ath5k_hw { unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); - bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, + int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index dfdaec0..bef967c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -668,7 +668,10 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) * return false w/o doing anything. MAC's that do * support it will return true w/o doing anything. */ - if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0)) + ret = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + if (ret < 0) + goto err; + if (ret > 0) __set_bit(ATH_STAT_MRRETRY, sc->status); /* @@ -1715,6 +1718,7 @@ ath5k_tasklet_rx(unsigned long data) break; else if (unlikely(ret)) { ATH5K_ERR(sc, "error in processing rx descriptor\n"); + spin_unlock(&sc->rxbuflock); return; } @@ -2126,8 +2130,9 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) "updated timers based on beacon TSF\n"); ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", - bc_tsf, hw_tsf, bc_tu, hw_tu, nexttbtt); + "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", + (unsigned long long) bc_tsf, + (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", intval & AR5K_BEACON_PERIOD, intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", @@ -2385,10 +2390,11 @@ ath5k_intr(int irq, void *dev_id) u64 tsf = ath5k_hw_get_tsf64(ah); sc->nexttbtt += sc->bintval; ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), tsf); + "SWBA nexttbtt: %x hw_tu: %x " + "TSF: %llx\n", + sc->nexttbtt, + TSF_TO_TU(tsf), + (unsigned long long) tsf); } else { ath5k_beacon_send(sc); } diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 1ab57aa..c2de2d9 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -45,7 +45,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, +static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *); @@ -3743,7 +3743,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* * Initialize a 4-word multirate tx descriptor on 5212 */ -static bool +static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) @@ -3783,10 +3783,10 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, #undef _XTX_TRIES - return true; + return 1; } - return false; + return 0; } /* diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c index 60d286e..e7d4aee 100644 --- a/drivers/net/wireless/p54usb.c +++ b/drivers/net/wireless/p54usb.c @@ -35,6 +35,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ + {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ @@ -62,6 +63,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ + {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 27ebd68..5e9a8ac 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -135,13 +135,15 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) while (skb_queue_len(&ring->queue)) { struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; struct sk_buff *skb; - struct ieee80211_tx_status status = { {0} }; + struct ieee80211_tx_status status; struct ieee80211_tx_control *control; u32 flags = le32_to_cpu(entry->flags); if (flags & RTL8180_TX_DESC_FLAG_OWN) return; + memset(&status, 0, sizeof(status)); + ring->idx = (ring->idx + 1) % ring->entries; skb = __skb_dequeue(&ring->queue); pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 0d71716..f445059 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -113,10 +113,12 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) static void rtl8187_tx_cb(struct urb *urb) { - struct ieee80211_tx_status status = { {0} }; + struct ieee80211_tx_status status; struct sk_buff *skb = (struct sk_buff *)urb->context; struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb; + memset(&status, 0, sizeof(status)); + usb_free_urb(info->urb); if (info->control) memcpy(&status.control, info->control, sizeof(status.control)); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 49127e4..76ef2d8 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -360,11 +360,14 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) { struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; struct sk_buff *skb; - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; skb = skb_dequeue(q); if (skb == NULL) return; + + memset(&status, 0, sizeof(status)); + tx_status(hw, skb, &status, 0); } @@ -389,7 +392,8 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error) if (unlikely(error || (cb->control->flags & IEEE80211_TXCTL_NO_ACK))) { - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; + memset(&status, 0, sizeof(status)); tx_status(hw, skb, &status, !error); } else { struct sk_buff_head *q = @@ -603,7 +607,9 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, tx_hdr = (struct ieee80211_hdr *)skb->data; if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) { - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; + + memset(&status, 0, sizeof(status)); status.flags = IEEE80211_TX_STATUS_ACK; status.ack_signal = stats->ssi; __skb_unlink(skb, q); diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index d976660c..78fd331 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -105,6 +105,12 @@ config SSB_DRIVER_MIPS If unsure, say N +# Assumption: We are on embedded, if we compile the MIPS core. +config SSB_EMBEDDED + bool + depends on SSB_DRIVER_MIPS + default y + config SSB_DRIVER_EXTIF bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" depends on SSB_DRIVER_MIPS && EXPERIMENTAL diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index 7be3975..e235144 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile @@ -1,5 +1,6 @@ # core ssb-y += main.o scan.o +ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o # host support ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 6fbf1c5..e586321 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -39,12 +39,14 @@ static inline void chipco_write32(struct ssb_chipcommon *cc, ssb_write32(cc->dev, offset, value); } -static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, - u32 mask, u32 value) +static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, + u32 mask, u32 value) { value &= mask; value |= chipco_read32(cc, offset) & ~mask; chipco_write32(cc, offset, value); + + return value; } void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, @@ -356,14 +358,29 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; } -void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) +u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) +{ + return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); +} + +u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) +{ + return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); +} + +u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) +{ + return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); +} + +u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) { - chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); + return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); } -void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) +u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) { - chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); + return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); } #ifdef CONFIG_SSB_SERIAL @@ -376,6 +393,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, unsigned int irq; u32 baud_base, div; u32 i, n; + unsigned int ccrev = cc->dev->id.revision; plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); irq = ssb_mips_irq(cc->dev); @@ -387,14 +405,39 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, chipco_read32(cc, SSB_CHIPCO_CLOCK_M2)); div = 1; } else { - if (cc->dev->id.revision >= 11) { + if (ccrev == 20) { + /* BCM5354 uses constant 25MHz clock */ + baud_base = 25000000; + div = 48; + /* Set the override bit so we don't divide it */ + chipco_write32(cc, SSB_CHIPCO_CORECTL, + chipco_read32(cc, SSB_CHIPCO_CORECTL) + | SSB_CHIPCO_CORECTL_UARTCLK0); + } else if ((ccrev >= 11) && (ccrev != 15)) { /* Fixed ALP clock */ baud_base = 20000000; + if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { + /* FIXME: baud_base is different for devices with a PMU */ + SSB_WARN_ON(1); + } div = 1; + if (ccrev >= 21) { + /* Turn off UART clock before switching clocksource. */ + chipco_write32(cc, SSB_CHIPCO_CORECTL, + chipco_read32(cc, SSB_CHIPCO_CORECTL) + & ~SSB_CHIPCO_CORECTL_UARTCLKEN); + } /* Set the override bit so we don't divide it */ chipco_write32(cc, SSB_CHIPCO_CORECTL, - SSB_CHIPCO_CORECTL_UARTCLK0); - } else if (cc->dev->id.revision >= 3) { + chipco_read32(cc, SSB_CHIPCO_CORECTL) + | SSB_CHIPCO_CORECTL_UARTCLK0); + if (ccrev >= 21) { + /* Re-enable the UART clock. */ + chipco_write32(cc, SSB_CHIPCO_CORECTL, + chipco_read32(cc, SSB_CHIPCO_CORECTL) + | SSB_CHIPCO_CORECTL_UARTCLKEN); + } + } else if (ccrev >= 3) { /* Internal backplane clock */ baud_base = ssb_clockspeed(bus); div = chipco_read32(cc, SSB_CHIPCO_CLKDIV) @@ -406,7 +449,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, } /* Clock source depends on strapping if UartClkOverride is unset */ - if ((cc->dev->id.revision > 0) && + if ((ccrev > 0) && !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) { if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) == SSB_CHIPCO_CAP_UARTCLK_INT) { @@ -428,7 +471,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE); uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA; /* Offset changed at after rev 0 */ - if (cc->dev->id.revision == 0) + if (ccrev == 0) uart_regs += (i * 8); else uart_regs += (i * 256); diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index fe55eb8..c3e1d3e6 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c @@ -27,12 +27,14 @@ static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) ssb_write32(extif->dev, offset, value); } -static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset, - u32 mask, u32 value) +static inline u32 extif_write32_masked(struct ssb_extif *extif, u16 offset, + u32 mask, u32 value) { value &= mask; value |= extif_read32(extif, offset) & ~mask; extif_write32(extif, offset, value); + + return value; } #ifdef CONFIG_SSB_SERIAL @@ -110,20 +112,35 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); } +void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, + u32 ticks) +{ + extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); +} + u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) { return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; } -void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) +u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) { return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), mask, value); } -void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) +u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) { return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), mask, value); } +u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) +{ + return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); +} + +u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) +{ + return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); +} diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 2faaa90..6d99a98 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -11,6 +11,7 @@ #include <linux/ssb/ssb.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/ssb/ssb_embedded.h> #include "ssb_private.h" @@ -27,6 +28,18 @@ void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value) ssb_write32(pc->dev, offset, value); } +static inline +u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset) +{ + return ssb_read16(pc->dev, offset); +} + +static inline +void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value) +{ + ssb_write16(pc->dev, offset, value); +} + /************************************************** * Code for hostmode operation. **************************************************/ @@ -66,6 +79,7 @@ int pcibios_plat_dev_init(struct pci_dev *d) base = &ssb_pcicore_pcibus_iobase; else base = &ssb_pcicore_pcibus_membase; + res->flags |= IORESOURCE_PCI_FIXED; if (res->end) { size = res->end - res->start + 1; if (*base & (size - 1)) @@ -88,10 +102,12 @@ int pcibios_plat_dev_init(struct pci_dev *d) static void __init ssb_fixup_pcibridge(struct pci_dev *dev) { + u8 lat; + if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) return; - ssb_printk(KERN_INFO "PCI: fixing up bridge\n"); + ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); /* Enable PCI bridge bus mastering and memory space */ pci_set_master(dev); @@ -101,7 +117,10 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev) pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); /* Make sure our latency is high enough to handle the devices behind us */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8); + lat = 168; + ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", + pci_name(dev), lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); @@ -117,8 +136,10 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc, u32 addr = 0; u32 tmp; - if (unlikely(pc->cardbusmode && dev > 1)) + /* We do only have one cardbus device behind the bridge. */ + if (pc->cardbusmode && (dev >= 1)) goto out; + if (bus == 0) { /* Type 0 transaction */ if (unlikely(dev >= SSB_PCI_SLOT_MAX)) @@ -279,14 +300,14 @@ static struct resource ssb_pcicore_mem_resource = { .name = "SSB PCIcore external memory", .start = SSB_PCI_DMA, .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1, - .flags = IORESOURCE_MEM, + .flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED, }; static struct resource ssb_pcicore_io_resource = { .name = "SSB PCIcore external I/O", .start = 0x100, .end = 0x7FF, - .flags = IORESOURCE_IO, + .flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED, }; static struct pci_controller ssb_pcicore_controller = { @@ -318,7 +339,16 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); udelay(1); /* Assertion time demanded by the PCI standard */ - /*TODO cardbus mode */ + if (pc->dev->bus->has_cardbus_slot) { + ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); + pc->cardbusmode = 1; + /* GPIO 1 resets the bridge */ + ssb_gpio_out(pc->dev->bus, 1, 1); + ssb_gpio_outen(pc->dev->bus, 1, 1); + pcicore_write16(pc, SSB_PCICORE_SPROM(0), + pcicore_read16(pc, SSB_PCICORE_SPROM(0)) + | 0x0400); + } /* 64MB I/O window */ pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, @@ -344,7 +374,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) /* Ok, ready to run, register it to the system. * The following needs change, if we want to port hostmode * to non-MIPS platform. */ - set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); + ssb_pcicore_controller.io_map_base = (unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000); + set_io_port_base(ssb_pcicore_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new * values. Not waiting at this point causes crashes of the machine. */ mdelay(10); diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c new file mode 100644 index 0000000..d3ade82 --- /dev/null +++ b/drivers/ssb/embedded.c @@ -0,0 +1,132 @@ +/* + * Sonics Silicon Backplane + * Embedded systems support code + * + * Copyright 2005-2008, Broadcom Corporation + * Copyright 2006-2008, Michael Buesch <mb@bu3sch.de> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include <linux/ssb/ssb.h> +#include <linux/ssb/ssb_embedded.h> + +#include "ssb_private.h" + + +int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) +{ + if (ssb_chipco_available(&bus->chipco)) { + ssb_chipco_watchdog_timer_set(&bus->chipco, ticks); + return 0; + } + if (ssb_extif_available(&bus->extif)) { + ssb_extif_watchdog_timer_set(&bus->extif, ticks); + return 0; + } + return -ENODEV; +} + +u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_in(&bus->chipco, mask); + else if (ssb_extif_available(&bus->extif)) + res = ssb_extif_gpio_in(&bus->extif, mask); + else + SSB_WARN_ON(1); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_in); + +u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_out(&bus->chipco, mask, value); + else if (ssb_extif_available(&bus->extif)) + res = ssb_extif_gpio_out(&bus->extif, mask, value); + else + SSB_WARN_ON(1); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_out); + +u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_outen(&bus->chipco, mask, value); + else if (ssb_extif_available(&bus->extif)) + res = ssb_extif_gpio_outen(&bus->extif, mask, value); + else + SSB_WARN_ON(1); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_outen); + +u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_control(&bus->chipco, mask, value); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_control); + +u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value); + else if (ssb_extif_available(&bus->extif)) + res = ssb_extif_gpio_intmask(&bus->extif, mask, value); + else + SSB_WARN_ON(1); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_intmask); + +u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value) +{ + unsigned long flags; + u32 res = 0; + + spin_lock_irqsave(&bus->gpio_lock, flags); + if (ssb_chipco_available(&bus->chipco)) + res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value); + else if (ssb_extif_available(&bus->extif)) + res = ssb_extif_gpio_polarity(&bus->extif, mask, value); + else + SSB_WARN_ON(1); + spin_unlock_irqrestore(&bus->gpio_lock, flags); + + return res; +} +EXPORT_SYMBOL(ssb_gpio_polarity); diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 9028ed5..bedb2b4 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -557,6 +557,7 @@ static int ssb_fetch_invariants(struct ssb_bus *bus, goto out; memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo)); memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom)); + bus->has_cardbus_slot = iv.has_cardbus_slot; out: return err; } @@ -569,6 +570,9 @@ static int ssb_bus_register(struct ssb_bus *bus, spin_lock_init(&bus->bar_lock); INIT_LIST_HEAD(&bus->list); +#ifdef CONFIG_SSB_EMBEDDED + spin_lock_init(&bus->gpio_lock); +#endif /* Powerup the bus */ err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 42dc6a3..e157c13 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -129,7 +129,8 @@ extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); /* * Display a 6 byte device address (MAC) in a readable format. */ -extern __pure char *print_mac(char *buf, const unsigned char *addr); +extern char *print_mac(char *buf, const unsigned char *addr); +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" #define MAC_BUF_SIZE 18 #define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE] __maybe_unused diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index d74e79b..b74b615 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -51,7 +51,7 @@ enum nf_inet_hooks { }; union nf_inet_addr { - u_int32_t all[4]; + __u32 all[4]; __be32 ip; __be32 ip6[4]; struct in_addr in; diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 91fef0c..3aff513 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -30,7 +30,6 @@ header-y += xt_mark.h header-y += xt_multiport.h header-y += xt_owner.h header-y += xt_pkttype.h -header-y += xt_policy.h header-y += xt_rateest.h header-y += xt_realm.h header-y += xt_sctp.h @@ -47,3 +46,4 @@ unifdef-y += nfnetlink.h unifdef-y += nfnetlink_compat.h unifdef-y += x_tables.h unifdef-y += xt_physdev.h +unifdef-y += xt_policy.h diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index 58b818e..51b18d8 100644 --- a/include/linux/netfilter/xt_hashlimit.h +++ b/include/linux/netfilter/xt_hashlimit.h @@ -61,7 +61,6 @@ struct xt_hashlimit_mtinfo1 { /* Used internally by the kernel */ struct xt_hashlimit_htable *hinfo __attribute__((aligned(8))); - struct xt_hashlimit_mtinfo1 *master __attribute__((aligned(8))); }; #endif /*_XT_HASHLIMIT_H*/ diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 9d5da8b..20add65 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -282,6 +282,13 @@ struct ssb_bus { struct ssb_boardinfo boardinfo; /* Contents of the SPROM. */ struct ssb_sprom sprom; + /* If the board has a cardbus slot, this is set to true. */ + bool has_cardbus_slot; + +#ifdef CONFIG_SSB_EMBEDDED + /* Lock for GPIO register access. */ + spinlock_t gpio_lock; +#endif /* EMBEDDED */ /* Internal-only stuff follows. Do not touch. */ struct list_head list; @@ -294,8 +301,13 @@ struct ssb_bus { /* The initialization-invariants. */ struct ssb_init_invariants { + /* Versioning information about the PCB. */ struct ssb_boardinfo boardinfo; + /* The SPROM information. That's either stored in an + * EEPROM or NVRAM on the board. */ struct ssb_sprom sprom; + /* If the board has a cardbus slot, this is set to true. */ + bool has_cardbus_slot; }; /* Type of function to fetch the invariants. */ typedef int (*ssb_invariants_func_t)(struct ssb_bus *bus, diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 4cb9954..536851b 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -51,9 +51,12 @@ #define SSB_CHIPCO_CAP_JTAGM 0x00400000 /* JTAG master present */ #define SSB_CHIPCO_CAP_BROM 0x00800000 /* Internal boot ROM active */ #define SSB_CHIPCO_CAP_64BIT 0x08000000 /* 64-bit Backplane */ +#define SSB_CHIPCO_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */ +#define SSB_CHIPCO_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */ #define SSB_CHIPCO_CORECTL 0x0008 #define SSB_CHIPCO_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */ #define SSB_CHIPCO_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ +#define SSB_CHIPCO_CORECTL_UARTCLKEN 0x00000008 /* UART clock enable (rev >= 21) */ #define SSB_CHIPCO_BIST 0x000C #define SSB_CHIPCO_OTPS 0x0010 /* OTP status */ #define SSB_CHIPCO_OTPS_PROGFAIL 0x80000000 @@ -357,6 +360,11 @@ struct ssb_chipcommon { u16 fast_pwrup_delay; }; +static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) +{ + return (cc->dev != NULL); +} + extern void ssb_chipcommon_init(struct ssb_chipcommon *cc); #include <linux/pm.h> @@ -382,11 +390,13 @@ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks); +/* Chipcommon GPIO pin access. */ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask); - -void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value); - -void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value); +u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value); +u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value); +u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value); +u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value); +u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value); #ifdef CONFIG_SSB_SERIAL extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h index a916435..91161f0 100644 --- a/include/linux/ssb/ssb_driver_extif.h +++ b/include/linux/ssb/ssb_driver_extif.h @@ -171,11 +171,15 @@ extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif, extern void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns); -u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); - -void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value); +extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, + u32 ticks); -void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value); +/* Extif GPIO pin access */ +u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); +u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value); +u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value); +u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value); +u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value); #ifdef CONFIG_SSB_SERIAL extern int ssb_extif_serial_init(struct ssb_extif *extif, @@ -200,5 +204,11 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, { } +static inline +void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, + u32 ticks) +{ +} + #endif /* CONFIG_SSB_DRIVER_EXTIF */ #endif /* LINUX_SSB_EXTIFCORE_H_ */ diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h index 9cfffb7..5e25bac 100644 --- a/include/linux/ssb/ssb_driver_pci.h +++ b/include/linux/ssb/ssb_driver_pci.h @@ -51,6 +51,11 @@ #define SSB_PCICORE_SBTOPCI1_MASK 0xFC000000 #define SSB_PCICORE_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ #define SSB_PCICORE_SBTOPCI2_MASK 0xC0000000 +#define SSB_PCICORE_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ +#define SSB_PCICORE_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ +#define SSB_PCICORE_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ +#define SSB_PCICORE_PCICFG3 0x0700 /* PCI config space 3 (rev >= 8) */ +#define SSB_PCICORE_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */ /* SBtoPCIx */ #define SSB_PCICORE_SBTOPCI_MEM 0x00000000 diff --git a/include/linux/ssb/ssb_embedded.h b/include/linux/ssb/ssb_embedded.h new file mode 100644 index 0000000..8d8dedf --- /dev/null +++ b/include/linux/ssb/ssb_embedded.h @@ -0,0 +1,18 @@ +#ifndef LINUX_SSB_EMBEDDED_H_ +#define LINUX_SSB_EMBEDDED_H_ + +#include <linux/types.h> +#include <linux/ssb/ssb.h> + + +extern int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks); + +/* Generic GPIO API */ +u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask); +u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value); +u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value); +u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value); +u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value); +u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value); + +#endif /* LINUX_SSB_EMBEDDED_H_ */ diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index c17fa1f..6512d85 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -14,8 +14,6 @@ /* capable of receiving packets */ #define IP6_TNL_F_CAP_RCV 0x20000 -#define IP6_TNL_MAX 128 - /* IPv6 tunnel */ struct ip6_tnl { diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index fc60c6d..77f04e4 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -366,8 +366,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); - DECLARE_MAC_BUF(mac); - DECLARE_MAC_BUF(mac2); + /* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING @@ -405,8 +404,11 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) pr_debug("%s: about to send skb: %p to dev: %s\n", __FUNCTION__, skb, skb->dev->name); - pr_debug(" %s %s %4hx %4hx %4hx\n", - print_mac(mac, veth->h_dest), print_mac(mac2, veth->h_source), + pr_debug(" " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n", + veth->h_dest[0], veth->h_dest[1], veth->h_dest[2], + veth->h_dest[3], veth->h_dest[4], veth->h_dest[5], + veth->h_source[0], veth->h_source[1], veth->h_source[2], + veth->h_source[3], veth->h_source[4], veth->h_source[5], veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 9e3d81c..de7a9f5 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -110,7 +110,7 @@ static struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag) } for (count = old_max; count < c->max_tag; count++) { c->reqs[count].status = REQ_STATUS_IDLE; - c->reqs[count].wq = kmalloc(sizeof(wait_queue_t), + c->reqs[count].wq = kmalloc(sizeof(wait_queue_head_t), GFP_ATOMIC); if (!c->reqs[count].wq) { printk(KERN_ERR "Couldn't grow tag array\n"); diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index e700cbf..ca64c1c 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c @@ -20,8 +20,8 @@ static int ebt_target_dnat(struct sk_buff *skb, unsigned int hooknr, { const struct ebt_nat_info *info = data; - if (skb_make_writable(skb, 0)) - return NF_DROP; + if (!skb_make_writable(skb, 0)) + return EBT_DROP; memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN); return info->target; diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index bfdf2fb..b8afe85 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c @@ -21,8 +21,8 @@ static int ebt_target_redirect(struct sk_buff *skb, unsigned int hooknr, { const struct ebt_redirect_info *info = data; - if (skb_make_writable(skb, 0)) - return NF_DROP; + if (!skb_make_writable(skb, 0)) + return EBT_DROP; if (hooknr != NF_BR_BROUTING) memcpy(eth_hdr(skb)->h_dest, diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index e252dab..5425333 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c @@ -22,8 +22,8 @@ static int ebt_target_snat(struct sk_buff *skb, unsigned int hooknr, { const struct ebt_nat_info *info = data; - if (skb_make_writable(skb, 0)) - return NF_DROP; + if (!skb_make_writable(skb, 0)) + return EBT_DROP; memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); if (!(info->target & NAT_ARP_BIT) && diff --git a/net/core/dev.c b/net/core/dev.c index 908f07c..fcdf03c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2900,7 +2900,7 @@ int __dev_addr_add(struct dev_addr_list **list, int *count, } } - da = kmalloc(sizeof(*da), GFP_ATOMIC); + da = kzalloc(sizeof(*da), GFP_ATOMIC); if (da == NULL) return -ENOMEM; memcpy(da->da_addr, addr, alen); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index a16cf1e..2328acb 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -358,11 +358,12 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, { struct neighbour *n; int key_len = tbl->key_len; - u32 hash_val = tbl->hash(pkey, dev); + u32 hash_val; NEIGH_CACHE_STAT_INC(tbl, lookups); read_lock_bh(&tbl->lock); + hash_val = tbl->hash(pkey, dev); for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { neigh_hold(n); @@ -379,11 +380,12 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, { struct neighbour *n; int key_len = tbl->key_len; - u32 hash_val = tbl->hash(pkey, NULL); + u32 hash_val; NEIGH_CACHE_STAT_INC(tbl, lookups); read_lock_bh(&tbl->lock); + hash_val = tbl->hash(pkey, NULL); for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { if (!memcmp(n->primary_key, pkey, key_len) && (net == n->dev->nd_net)) { @@ -507,6 +509,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, if (tbl->pconstructor && tbl->pconstructor(n)) { if (dev) dev_put(dev); + release_net(net); kfree(n); n = NULL; goto out; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 61ac8d0..2bd9c5f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -689,10 +689,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, [IFLA_MTU] = { .type = NLA_U32 }, + [IFLA_LINK] = { .type = NLA_U32 }, [IFLA_TXQLEN] = { .type = NLA_U32 }, [IFLA_WEIGHT] = { .type = NLA_U32 }, [IFLA_OPERSTATE] = { .type = NLA_U8 }, [IFLA_LINKMODE] = { .type = NLA_U8 }, + [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_NET_NS_PID] = { .type = NLA_U32 }, }; @@ -720,6 +722,21 @@ static struct net *get_net_ns_by_pid(pid_t pid) return net; } +static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) +{ + if (dev) { + if (tb[IFLA_ADDRESS] && + nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) + return -EINVAL; + + if (tb[IFLA_BROADCAST] && + nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) + return -EINVAL; + } + + return 0; +} + static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, struct nlattr **tb, char *ifname, int modified) { @@ -892,12 +909,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto errout; } - if (tb[IFLA_ADDRESS] && - nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) - goto errout_dev; - - if (tb[IFLA_BROADCAST] && - nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) + if ((err = validate_linkmsg(dev, tb)) < 0) goto errout_dev; err = do_setlink(dev, ifm, tb, ifname, 0); @@ -1018,6 +1030,9 @@ replay: else dev = NULL; + if ((err = validate_linkmsg(dev, tb)) < 0) + return err; + if (tb[IFLA_LINKINFO]) { err = nla_parse_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO], ifla_info_policy); diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 76b9c68..8d58d85 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -372,7 +372,8 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key) static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) { struct fn_hash *table = (struct fn_hash *) tb->tb_data; - struct fib_node *new_f, *f; + struct fib_node *new_f = NULL; + struct fib_node *f; struct fib_alias *fa, *new_fa; struct fn_zone *fz; struct fib_info *fi; @@ -496,7 +497,6 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) err = -ENOBUFS; - new_f = NULL; if (!f) { new_f = kmem_cache_zalloc(fn_hash_kmem, GFP_KERNEL); if (new_f == NULL) @@ -512,7 +512,7 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) if (new_fa->fa_info != NULL) { new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); if (new_fa == NULL) - goto out_free_new_f; + goto out; } new_fa->fa_info = fi; new_fa->fa_tos = tos; @@ -540,9 +540,9 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) &cfg->fc_nlinfo, 0); return 0; -out_free_new_f: - kmem_cache_free(fn_hash_kmem, new_f); out: + if (new_f) + kmem_cache_free(fn_hash_kmem, new_f); fib_release_info(fi); return err; } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 63f6917..906cb1a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -259,16 +259,8 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - else { - int i; - for (i=1; i<100; i++) { - sprintf(name, "gre%d", i); - if (__dev_get_by_name(&init_net, name) == NULL) - break; - } - if (i==100) - goto failed; - } + else + sprintf(name, "gre%%d"); dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup); if (!dev) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index da28158..e77e3b8 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -221,16 +221,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - else { - int i; - for (i=1; i<100; i++) { - sprintf(name, "tunl%d", i); - if (__dev_get_by_name(&init_net, name) == NULL) - break; - } - if (i==100) - goto failed; - } + else + sprintf(name, "tunl%%d"); dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); if (dev == NULL) diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 45fa4e2..3f4222b 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c @@ -19,7 +19,7 @@ target(struct sk_buff *skb, unsigned char *arpptr; int pln, hln; - if (skb_make_writable(skb, skb->len)) + if (!skb_make_writable(skb, skb->len)) return NF_DROP; arp = arp_hdr(skb); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 6bda110..fe05da4 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -283,8 +283,8 @@ static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e) { int diff; - int err; struct iphdr *user_iph = (struct iphdr *)v->payload; + struct sk_buff *nskb; if (v->data_len < sizeof(*user_iph)) return 0; @@ -296,14 +296,16 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e) if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { - err = pskb_expand_head(e->skb, 0, + nskb = skb_copy_expand(e->skb, 0, diff - skb_tailroom(e->skb), GFP_ATOMIC); - if (err) { + if (!nskb) { printk(KERN_WARNING "ip_queue: error " - "in mangle, dropping packet: %d\n", -err); - return err; + "in mangle, dropping packet\n"); + return -ENOMEM; } + kfree_skb(e->skb); + e->skb = nskb; } skb_put(e->skb, diff); } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index cd94064..2a124e9a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -229,18 +229,11 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) char name[IFNAMSIZ]; int err; - if (p->name[0]) { + if (p->name[0]) strlcpy(name, p->name, IFNAMSIZ); - } else { - int i; - for (i = 1; i < IP6_TNL_MAX; i++) { - sprintf(name, "ip6tnl%d", i); - if (__dev_get_by_name(&init_net, name) == NULL) - break; - } - if (i == IP6_TNL_MAX) - goto failed; - } + else + sprintf(name, "ip6tnl%%d"); + dev = alloc_netdev(sizeof (*t), name, ip6_tnl_dev_setup); if (dev == NULL) goto failed; diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e869916..cc2f9af 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -285,8 +285,8 @@ static int ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e) { int diff; - int err; struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; + struct sk_buff *nskb; if (v->data_len < sizeof(*user_iph)) return 0; @@ -298,14 +298,16 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e) if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { - err = pskb_expand_head(e->skb, 0, + nskb = skb_copy_expand(e->skb, 0, diff - skb_tailroom(e->skb), GFP_ATOMIC); - if (err) { + if (!nskb) { printk(KERN_WARNING "ip6_queue: OOM " "in mangle, dropping packet\n"); - return err; + return -ENOMEM; } + kfree_skb(e->skb); + e->skb = nskb; } skb_put(e->skb, diff); } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e77239d..dde7801 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -164,16 +164,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); - else { - int i; - for (i=1; i<100; i++) { - sprintf(name, "sit%d", i); - if (__dev_get_by_name(&init_net, name) == NULL) - break; - } - if (i==100) - goto failed; - } + else + sprintf(name, "sit%%d"); dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); if (dev == NULL) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index a48b20f..0043d3a 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -443,8 +443,8 @@ err_out: static int nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) { + struct sk_buff *nskb; int diff; - int err; diff = data_len - e->skb->len; if (diff < 0) { @@ -454,14 +454,16 @@ nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) if (data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { - err = pskb_expand_head(e->skb, 0, + nskb = skb_copy_expand(e->skb, 0, diff - skb_tailroom(e->skb), GFP_ATOMIC); - if (err) { + if (!nskb) { printk(KERN_WARNING "nf_queue: OOM " "in mangle, dropping packet\n"); - return err; + return -ENOMEM; } + kfree_skb(e->skb); + e->skb = nskb; } skb_put(e->skb, diff); } diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 744c7f2..5418ce5 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -774,9 +774,6 @@ hashlimit_mt_check(const char *tablename, const void *inf, return false; } mutex_unlock(&hlimit_mutex); - - /* Ugly hack: For SMP, we only want to use one set */ - info->master = info; return true; } diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c index 4f984dc..500528d 100644 --- a/net/netfilter/xt_iprange.c +++ b/net/netfilter/xt_iprange.c @@ -102,7 +102,7 @@ iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b) int r; for (i = 0; i < 4; ++i) { - r = (__force u32)a->s6_addr32[i] - (__force u32)b->s6_addr32[i]; + r = ntohl(a->s6_addr32[i]) - ntohl(b->s6_addr32[i]); if (r != 0) return r; } diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c index 9b8ed39..627e0f3 100644 --- a/net/netfilter/xt_u32.c +++ b/net/netfilter/xt_u32.c @@ -26,7 +26,6 @@ static bool u32_match_it(const struct xt_u32 *data, u_int32_t pos; u_int32_t val; u_int32_t at; - int ret; /* * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17" @@ -40,8 +39,8 @@ static bool u32_match_it(const struct xt_u32 *data, if (skb->len < 4 || pos > skb->len - 4) return false; - ret = skb_copy_bits(skb, pos, &n, sizeof(n)); - BUG_ON(ret < 0); + if (skb_copy_bits(skb, pos, &n, sizeof(n)) < 0) + BUG(); val = ntohl(n); nnums = ct->nnums; @@ -67,9 +66,9 @@ static bool u32_match_it(const struct xt_u32 *data, pos > skb->len - at - 4) return false; - ret = skb_copy_bits(skb, at + pos, &n, - sizeof(n)); - BUG_ON(ret < 0); + if (skb_copy_bits(skb, at + pos, &n, + sizeof(n)) < 0) + BUG(); val = ntohl(n); break; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d47d578..44797ad 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6488,6 +6488,7 @@ struct proto sctp_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + .sockets_allocated = &sctp_sockets_allocated, REF_PROTO_INUSE(sctp) }; @@ -6521,6 +6522,7 @@ struct proto sctpv6_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + .sockets_allocated = &sctp_sockets_allocated, REF_PROTO_INUSE(sctpv6) }; #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |